Results 1 to 10 of 32

Thread: Beginner's Programming Challenge 18

Hybrid View

  1. #1
    Join Date
    Apr 2008
    Beans
    286

    Beginner's Programming Challenge 18

    Hi all, as I am the winner of Beginner's Programming Challenge 17 I have the honour of bringing to you Beginner's Programming Challenge 18.

    This time the challenge involves some basic cryptography. You must implement the Vigenère cipher in a programming language of your choice. Your program must prompt the user for a plaintext (the message) and a key (the password) and it should output the corresponding cyphertext (the encrypted message). For the sake of simplicity both the message and the key must contain only uppercase letters of the English alphabet.

    For bonus points your program should also be able to decrypt a message given a cyphertext and a key.

    This is a beginner's challenge, so the source code shouldn't be hard to read. Also please include plenty of comments.

    Some reading:
    http://en.wikipedia.org/wiki/Caesar_cipher
    http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher

    Best of luck to all.

    Rouslan
    Last edited by roccivic; January 18th, 2011 at 10:08 PM.

  2. #2
    Join Date
    Apr 2007
    Location
    NorCal
    Beans
    1,149
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: Beginner's Programming Challenge 18

    Haskell:
    Code:
    import Data.Char
    import System(getArgs)
    
    data Crypt = Encrypt | Decrypt deriving (Eq)
    
    -- Takes two characters, one from the original string
    -- and one from the corresponding index of the key string.
    -- Returns the encrypted (or decrypted) character.
    vigenere :: Crypt -> Char -> Char -> Char
    vigenere e old key = chr $ 65 + ((p_i `f` k_i) `mod` 26)
      where p_i = (ord old) - 65
            k_i = (ord key) - 65
            f   = if e == Encrypt then (+) else (-)
            
    -- Expects 3 command line arguments, the password, the key
    -- and an 'e' or 'd' if you want to encrypt or decrypt
    -- respectively. The password will be cycled as necessary
    -- to be the same length as the source text
    main = do
      args <- getArgs
      let [source, pass, x] = take 3 args 
          password = take (length source) (cycle pass)
          e = case (head x) of
                   'e' -> Encrypt
                   'd' -> Decrypt
        in putStrLn $ zipWith (vigenere e) source password
    Here's a similar approach in Python, whited out for the time being:

    Code:
    import sys
    import operator
    from itertools import cycle, islice
    
    def vigenere(f, old, key):
        p_i = ord(old) - 65
        k_i = ord(key) - 65
    
        return chr(65 + (f(p_i, k_i) % 26))
    
    def main():
        [source, passw, x] = sys.argv[1:4]
        password = list(islice(cycle(passw), 0, len(source)))
        if x == "e":
            f = operator.add
        elif x == "d":
            f = operator.sub
    
        s = ""
        for i in xrange(len(source)):
            s += vigenere(f, source[i], password[i])
    
        print s
    
    main()
    
    Last edited by schauerlich; January 22nd, 2011 at 12:47 AM.
    Posting code? Use the [code] or [php] tags.
    I don't care, I'm still free. You can't take the sky from me.

  3. #3
    Join Date
    May 2009
    Beans
    522

    Re: Beginner's Programming Challenge 18

    Quote Originally Posted by schauerlich View Post
    Code:
    import Data.Char
    import System(getArgs)
    
    -- Takes two characters, one from the original string
    -- and the corresponding character of the key string.
    -- To encrypt, f should be (+); to decrypt, (-)
    vigenere :: (Int -> Int -> Int) -> Char -> Char -> Char
    vigenere f old key = chr $ 65 + ((f p_i k_i) `mod` 26)
      where p_i = (ord old) - 65
            k_i = (ord key) - 65
    
    -- Expects 3 command line arguments, the password, the key
    -- and an 'e' or 'd' if you want to encrypt or decrypt
    -- respectively. The password will be cycled as necessary
    -- to be the same length as the source text
    main = do
      args <- getArgs
      let [source, pass, x] = take 3 args 
          password = take (length source) (cycle pass)
          f = case (head x) of
                   'e' -> (+) 
                   'd' -> (-)
        in putStrLn $ zipWith (vigenere f) source password
    what language is that?

  4. #4
    Join Date
    Sep 2009
    Location
    Canada, Montreal QC
    Beans
    1,809
    Distro
    Ubuntu 11.10 Oneiric Ocelot

    Re: Beginner's Programming Challenge 18

    It looks like Haskell to me...
    I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones.
    Freedom is measured in Stallmans.
    Projects: gEcrit

  5. #5
    Join Date
    Sep 2009
    Location
    Canada, Montreal QC
    Beans
    1,809
    Distro
    Ubuntu 11.10 Oneiric Ocelot

    Re: Beginner's Programming Challenge 18

    Just wanted to get rid of a bad number of posts, bump!
    I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones.
    Freedom is measured in Stallmans.
    Projects: gEcrit

  6. #6
    Join Date
    Apr 2007
    Location
    NorCal
    Beans
    1,149
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: Beginner's Programming Challenge 18

    Quote Originally Posted by unknownPoster View Post
    what language is that?
    Haskell.
    Posting code? Use the [code] or [php] tags.
    I don't care, I'm still free. You can't take the sky from me.

  7. #7
    Join Date
    Apr 2007
    Location
    NorCal
    Beans
    1,149
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: Beginner's Programming Challenge 18

    Bump, since there are hardly any entries.
    Posting code? Use the [code] or [php] tags.
    I don't care, I'm still free. You can't take the sky from me.

  8. #8
    Join Date
    Jul 2007
    Location
    Austin, TX
    Beans
    Hidden!
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: Beginner's Programming Challenge 18

    Quote Originally Posted by schauerlich View Post
    Bump, since there are hardly any entries.
    This was posted the same week university started back up for me, maybe others are busy as well?

    Here's an encrypter in Go. I'll add the decrypter tomorrow if I have time.

    Code:
    // UFBPC 18
    // @TAGS { UFBPC }
    package main
    
    import "fmt"
    import "bufio"
    import "os"
    
    func main() {
        bufin := bufio.NewReader(os.Stdin)
        
        fmt.Printf("Enter Message: ")
        mess,_ := bufin.ReadString('\n')
        mess = mess[0:len(mess)-1] // trim off newline
        
        fmt.Printf("Enter Key: ")
        key,_ := bufin.ReadString('\n')
        key = key[0:len(key)-1] 
        
        enc := ""
        for i:=0; i<len(mess); i++ {
            enc += vig(mess[i], key[0])
            key = cycle(key)
        }
        
        fmt.Printf("Encrypted: %s\n", enc)
    }
    
    func cycle(in string) string {
        ret := in[1:]
        ret += in[0:1];
        return ret
    }
    
    func vig( m, k uint8 ) string {
        p_i := m - 65
        k_i := k - 65
        u_i := (65 + (p_i + k_i) % 26)
        return string(u_i);
    }
    Instructions for getting a Go compiler going: http://golang.org/doc/install.html
    Not as easy as something pre-packaged but it's pretty straight forward none the less.
    Last edited by Queue29; January 24th, 2011 at 05:42 AM.

  9. #9
    Join Date
    Dec 2010
    Location
    Denmark
    Beans
    0
    Distro
    Xubuntu

    Re: Beginner's Programming Challenge 18

    Python solution.
    Code:
    import string,sys
    
    letters = string.uppercase
    
    def vigenere(p,k,d):
    	if d:
    		i = ( ord(p) - ord(k) - 130) % len(letters)
    	else:
    		i = ( ord(p) + ord(k) - 130) % len(letters)
    	return letters[i]
    
    if len(sys.argv)<4:
    	print "Usage:",sys.argv[0],"[plaintext|ciphertext] key [encrypt|decrypt]"
    	print "Example:",sys.argv[0]," attackatdawn lemon encrypt"
    	sys.exit(1)
    
    text = sys.argv[1].upper()
    key = sys.argv[2].upper()
    
    decrypt = False
    
    if sys.argv[3]=='decrypt':
    	decrypt = True
    
    c=0
    result = ''
    for t in text:
    	result = result + vigenere(t,key[c % len(key)],decrypt)
    	c = c + 1
    
    print result

  10. #10
    Join Date
    Mar 2010
    Location
    London
    Beans
    924

    Re: Beginner's Programming Challenge 18

    Here my shot at it in Java, I decided to implement it by actually creating the cypher table and looking up the characters.

    Code:
    public class Cypher {
        
        private static final int ROWS = 26;
        private static final int COLS = 26;
        private static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private static char[][] table;
        
        //takes 2 args: text, key and 'e' or 'd'
        public static void main(String[] args) {
        	//init the table
        	table = new char[ROWS][COLS];
        	for (int r = 0, offset = 0; r < ROWS; r++, offset++) {
        	    for (int c = 0, pos = offset; c < COLS; c++, pos++) {
        		if (pos == alphabet.length()) {
        	            pos = 0;
        		}
        		table[r][c] = alphabet.charAt(pos);
        	    }
        	}  	
            //Make string upper case
            args[0] = args[0].toUpperCase();
            args[1] = args[1].toUpperCase();
        	//append key if needed
        	while (args[0].length() > args[1].length()) {
        	    args[1] += args[1];
        	}
        	args[1] = args[1].substring(0, args[0].length()+1);	 
        	//loop through each character and encrypt/decrypt   	
        	int pos = 0;
        	StringBuilder output = new StringBuilder(args[0].length());
        	for (int i = 0; i < args[0].length(); i++) {
        	    if (args[2].equalsIgnoreCase("e")) {
        		output.append(encryptChar(args[0].charAt(i), args[1].charAt(i)));
        	    } else if (args[2].equalsIgnoreCase("d")) {
        		output.append(decryptChar(args[0].charAt(i), args[1].charAt(i)));
        	    }
        	} 
        	System.out.println(output.toString()); //print output
        }
        
        //Encrypt character by looking up in table
        private static char encryptChar(char orig, char key) {
        	int r = 0; 
        	int c = 0;
        	for (; c < COLS; c++) {
        	    if (table[c][0] == orig) {break;}
        	}
        	for (; r < ROWS; r++) {
        	    if (table[0][r] == key) {break;}
        	}
        	return table[r][c];
        }
        
        //Decrypt character by looking up in table
        private static char decryptChar(char crypted, char key) {
        	int r = 0;
        	for (; r < ROWS; r++) {
        	    if (table[0][r] == key) {break;}
        	}
        	int c = 0;
        	for (; c < COLS; c++) {
        	    if (table[c][r] == crypted) {break;}
        	}
        	return table[0][c];
        }
    }
    Last edited by KdotJ; January 19th, 2011 at 03:07 AM.
    - "Make me a coffee..."
    - "No"
    - "sudo make me a coffee"
    - "OK"

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •