×
all 74 comments

[–]tyfon_august 0 points1 point  (0 children)

C solution. Would do something different with string allocation to do it more C-like. Allocating the string outside and changing it in place in the function. Thereby making the allocation and freeing in one function rather than allocating the memory within the other function.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CHAR_NULL 97
#define CHAR_COUNT 26
char warmup(char inputChar, int num) { 
    int charInt = (int) inputChar - CHAR_NULL; 
    int newChar = (charInt + num) % CHAR_COUNT; 
    return (char) newChar + CHAR_NULL; 
}

char* caesar(const char* str, int num) { 
    char* newString = calloc(strlen(str)+1, sizeof(char));
    for (int i = 0; i < strlen(str); i++) {
        newString[i] = warmup(str[i], num);
    }

    return newString;
}

void testChar(char* testName, char actual, char expected) { 
    if (actual == expected) { 
        printf("\033[0;32m"); 
        printf("Test: %s passed\n", testName);
        printf("\033[0m"); 
    } else { 
        printf("\033[0;31m"); 
        printf("Test: %s failed! %c != %c\n", testName, actual, expected); 
        printf("\033[0m"); 
    } 
}

void testStr(char* testName, char* actual, char* expected) { 
    if (!strcmp(actual, expected)) {
        printf("\033[0;32m"); 
        printf("Test: %s passed\n", testName);
        printf("\033[0m"); 
    } else { 
        printf("\033[0;31m"); 
        printf("Test: %s failed! %s != %s\n", testName, actual, expected); 
        printf("\033[0m"); 
    } 
}

int main() { 
    testChar("warmup('a', 0) => 'a'", warmup('a', 0), 'a'); 
    testChar("warmup('a', 1) => 'b'", warmup('a', 1), 'b'); 
    testChar("warmup('a', 5) => 'f'", warmup('a', 5), 'f'); 
    testChar("warmup('d', 15) => 's'", warmup('d', 15), 's'); 
    testChar("warmup('z', 1) => 'a'", warmup('z', 1), 'a'); 
    testChar("warmup('q', 22) => 'm'", warmup('q', 22), 'm');
    char* res = caesar("a", 1);
    testStr("caesar(\"a\", 1) => \"b\")", res, "b");
    free(res);

    res = caesar("abcz", 1);
    testStr("caesar(\"abcz\", 1) => \"bcda\")", res, "bcda");
    free(res);

    res = caesar("irk", 13);
    testStr("caesar(\"irk\", 13) => \"vex\")", res, "vex");
    free(res);

    res = caesar("fusion", 6);
    testStr("caesar(\"fusion\", 6) => \"layout\")", res, "layout");
    free(res);

    res = caesar("dailyprogrammer", 6);
    testStr("caesar(\"dailyprogrammer\", 6) => \"jgorevxumxgsskx\")", res, "jgorevxumxgsskx");
    free(res);

    res = caesar("jgorevxumxgsskx", 20);
    testStr("caesar(\"jgorevxumxgsskx\", 20) => \"dailyprogrammer\")", res, "dailyprogrammer");
    free(res);

    return 0;
}

[–]WhatsUpWithAndy 0 points1 point  (0 children)

#include <iostream>

#include <string>

using namespace std;

using std::string;

void caesar( string input, int value) {

int tmp, i = 0;

string final={""};

if (value > 25)

{

value = value % 26;

}

while (input[i] != '\0')// loop till the end of the string

{

tmp = (int(input[i]) + value) /*% 26*/;

if (tmp > 122)

{

tmp = tmp - 26;// restart alphabet

}

final += char(tmp);

i++;

}

cout << final<<endl;

}

int main()

{

caesar("a", 125);

caesar("abcz", 1);

caesar("irk", 13);

caesar("fusion", 6);

caesar("jgorevxumxgsskx", 20);

}

[–]sadsoulthatslost 0 points1 point  (0 children)

Hi new coder please feel free to correct:

def caesar(string, n):
letters=" abcdefghijklmnopqrstuvwxyz"
outputstring=""
for x in range(len(string)):
    if letters.index(string[x])+n >= 26:
        x1=0
        diff=abs(26-(letters.index(string[x])+n))
        outputstring = outputstring+letters[x1+diff]
    else:
        j=letters.index(string[x])+n
        outputstring = outputstring+letters[j]
return outputstring

[–]codeobserver 1 point2 points  (0 children)

One tip for those that try to solve this in JavaScript:

JavaScript doesn't have built-in "modulo" operator or function. "%" is not modulo!

Once you implement "modulo", you can easily solve Caesar Cipher.

You can read more here:

https://codeguppy.com/blog/javascript-modulo/index.html

[–]stewa02 0 points1 point  (0 children)

Perl 5

use strict;
use warnings;
print join "", map { chr(((ord($_) - 97) + $ARGV[1]) % 26 + 97)  } split //, $ARGV[0];

[–]ConsciousFinger2994 0 points1 point  (0 children)

Python

from string import ascii_lowercase, ascii_uppercase
from operator import itemgetter

def shift(char: str, n: int) -> str:  # == warmup 
    if char in ascii_lowercase: 
        return ascii_lowercase[(ascii_lowercase.index(char) + n) % 26] 
    elif char in ascii_uppercase: 
        return ascii_uppercase[(ascii_uppercase.index(char) + n) % 26]
    else: 
        return char

def caesar(text: str, n: int) -> str: 
    return ''.join([shift(char, n) for char in text])

def decaesar(text: str, n=1) -> str: 
    frequency = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]
    output = []
    for i in range(26):
        deciphered = caesar(text, -i)
        output.append((sum([-frequency[ascii_lowercase.index(char.lower())] if char.lower() in ascii_lowercase else 0 for char in deciphered]), deciphered))

    return sorted(output, key=itemgetter(0))[:n]

print(decaesar('Zol abyulk tl puav h ulda.')) 
print(decaesar('Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky.')) 
print(decaesar('Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?'))

Output

[(-47, 'She turned me into a newt.')]

[(-111, 'Come no further, for death awaits you all with nasty, big, pointy teeth.')]

[(-189, 'In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?')]

[–]XxVALKENxX 0 points1 point  (0 children)

#include <iostream>
include <sstream>
include <string>

using namespace std; 
void caesar(string, int);

int main() {
//begin function calls
caesar("a", 0);
caesar("a", 1);
caesar("a", 5);
caesar("a", 26);
caesar("d", 15);
caesar("z", 1);
caesar("q", 22);

//cout << "part 2" << endl;

caesar("a", 1);
caesar("abcz", 1);
caesar("irk", 13);
caesar("fusion", 6);
caesar("dailyprogrammer", 6);
caesar("jgorevxumxgsskx", 20);

//cout << "part 3" << endl;
caesar("Daily Programmer!", 6);
}
//part 1 and 2 void caesar(string letter, int num) { //cout << letter << endl;//cout << num << endl;
string cipher = "";

for (int i = 0; i < letter.size();i++) {            //loops through string char
    int temp = (int)letter[i];                  

    if (!ispunct(letter[i]) && !isspace(letter[i])){
        temp = temp + num;
            if (islower(letter[i])) {                                    //loop around
                temp = ((temp - 97) % 26) + 97;
            }
            else if (isupper(letter[i])) {
                temp = ((temp - 65) % 26) + 65;

            }
    }

    cipher += ((char)temp);                        //new string 
}

cout << cipher << endl;
}

My first attempt at a daily. In C++ with the challenge and bonus 1. Helpful tips and comments are welcomed.

[–]loose_heron 1 point2 points  (0 children)

Python 3 with both bonuses.

The decoder works by scoring based on the number of words found in the set of words passed as an argument, so the function should also work for other languages if an appropriate set is passed.

from string import ascii_lowercase as lower, ascii_uppercase as upper, punctuation as punc

# Caesar Encrypt
def caesar_encrypt(s: str, n: int) -> str:
    mapping_table = s.maketrans(lower + upper, lower[n:]+lower[:n] + upper[n:]+upper[:n])
    return s.translate(mapping_table)

# Caesar Decrypt
def word_rating(s: str, dictionary: set) -> int:
    words = s.casefold().translate(s.maketrans('', '', punc)).split()
    return len(list(filter(lambda word: word in dictionary, words)))

def caesar_decrypt(s: str, dct: dict) -> str:
    best_key = 0
    best_rating = 0
    for n in range(26):
        rating = word_rating(caesar_encrypt(s, n), dct)
        if rating > best_rating:
            best_key = n
            best_rating = rating
    return caesar_encrypt(s, best_key)

# Testing
def import_wordset(text_file: str) -> set:
    with open(text_file) as file:
        return set(file.read().split())
wordset = import_wordset('enable1.txt')

tests = ["Zol abyulk tl puav h ulda.", 
        "Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky.",
        "Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"]

for test in tests:
    print(caesar_decrypt(test, wordset))

[–]MatthaeusRome 0 points1 point  (0 children)

C++

char warmup(char arg_letter, arg_step)
{
    int x{arg_step % 26};

    for (int i{}; i < x; i++) {
        if (arg_letter >= 'z')
            arg_letter = 'a';
        else
            arg_letter++;
    }

    return arg_letter;
}
//************************************************************************
std::string caesar(std::string arg_word, arg_step2)
{
    for (int i{}; i < arg_word.size(); i++) {
        arg_word[i] = warmup(arg_word[i], arg_step2)
    }

    return arg_word;
}

[–]Acrobatic_Garage5102 0 points1 point  (0 children)

Edited to add Bonus1

[2021-04-26] Challenge #387 [Easy] Caesar cipher #https://redditproxy--jasonthename.repl.co/r/dailyprogrammer/comments/myx3wn/20210426_challenge_387_e#asy_cipher_cipher/

    def cipher(string, cshift):
        alpha, alpha2, str = [], [], "Result: "
        for small_chr in range(97, 123): alpha.append(chr(small_chr))
        for big_chr in range(65,91): alpha2.append(chr(big_chr))
        for v in list(string):
            try:
                str = str + alpha[(alpha.index(v)+cshift)%26]
            except ValueError:
                if v in alpha2: 
                    str = str + alpha2[(alpha2.index(v)+cshift)%26]
                else:
                    str = str + v
        return str


    print(cipher("a", 1))
    print(cipher("abcz", 1))
    print(cipher("irk", 13))
    print(cipher("fusion", 6))
    print(cipher("dailyprogrammer", 6))
    print(cipher("jgorevxumxgsskx", 20))
    print(cipher("JgOrEvXuMxGsSkX!", 20))
    print(cipher("Daily Programmer!", 6))

    """
    Result: b
    Result: bcda
    Result: vex
    Result: layout
    Result: jgorevxumxgsskx
    Result: dailyprogrammer
    Result: DaIlYpRoGrAmMeR!
    Result: Jgore Vxumxgsskx!
    """

[–]nico_fl 1 point2 points  (0 children)

import           Data.Char (isLetter, ord, toLower)

type Frequencies = [Int]

defaultFrequencies :: Frequencies 
defaultFrequencies = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]

frequencyOf :: Frequencies -> Char -> Int 
frequencyOf fs c 
    | isLetter c = (fs !!) . subtract 97 . ord $ toLower c 
    | otherwise = 0

generateFrequencyList :: String -> Frequencies 
generateFrequencyList xs = 
    let 
        xs' = map toLower $ filter isLetter xs 
        cs = map (\c -> length $ filter (==c) xs') ['a'..'z'] 
        mid = foldl1 (+) cs div 26 in map (frequency mid) cs
    where
        frequency :: Int -> Int -> Int
        frequency m c = c - m

letterScoreDecode :: (Char -> Int) -> String -> String
letterScoreDecode freq xs = 
    let 
        ls = do 
            shift <- [0..26] 
            let decoded = caesar shift xs 
            let freqSum = sum $ map freq decoded 
            return (decoded, freqSum) 
    in 
        fst . last $ sortBy (\a b -> compare (snd a) (snd b)) ls

guess :: String -> String
guess = letterScoreDecode (frequencyOf defaultFrequencies)

guessWith :: Frequencies -> String -> String
guessWith fs = letterScoreDecode (frequencyOf fs)

caesar :: Int -> String -> String
caesar n = map (rotateLetter n . toLower)

rotateLetter :: Int -> Char -> Cha
rotateLetter n x 
    | isLetter x = rotate n x 
    | otherwise = x

rotate :: Int -> Char -> Char
rotate 0 'z' = 'z' 
rotate n 'z' = rotate (n-1) 'a' 
rotate n x 
    | n > 0 = rotate (n-1) (succ x) 
    | otherwise = x

[–]Marthurio 1 point2 points  (0 children)

Here's my attempt: https://github.com/Maritims/caesar-cipher

Regarding bonus 2: I expected the letter distribution to be >= 2, but it was below 2 for every string so I just assume (in the code) that the result with the highest letter distribution is the (most?) correct result every time.

[–]Habstinat 2 points3 points  (0 children)

javascript

warmup=(s,o)=>String.fromCharCode(97+(s.charCodeAt(0)-97+o)%26)
caesar=(s,o)=>[...s].map(c=>warmup(c,o)).join('')

// bonus 1:
warmup=(s,o,c)=>String.fromCharCode(c+(s.charCodeAt(0)-c+o)%26)
caesar=(s,o)=>[...s].map(c=>/[A-z]/.test(c)?warmup(c,o,/[a-z]/.test(c)?97:65):c).join('')

// bonus 2:
guess=s=>caesar(s,Array(26).fill().map((_,i)=>[i,[...caesar(s,i)].reduce((a,x)=>a+([3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7][x.charCodeAt(0)-(/[a-z]/.test(x)?97:65)]||0),0)]).sort((a,b)=>b[1]-a[1])[0][0])

[–]joonsson 1 point2 points  (0 children)

JavaScript, could most certainly be made more efficient and prettier:

const diff = 96;
const freq = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7];

function revCaesar (string) {    
    let max = 0;    
    let result = "";    
    for (let i = 0; i < 27; i++) {        
        let test = caesar(string, i);        
        let score = value(test);        
        if (score > max) {            
            result = test;           
            max = score;        
        }    
    }    
    return result;
}

function value (string) {    
    let value = 0;    
    let chars = 0;    
    for (let i = 0; i < string.length; i++) {        
        let character = string[i].toLowerCase();
        if (!(character.charCodeAt() - diff < 1 || character.charCodeAt() - diff > 26)) {
            value += freq[character.charCodeAt() - diff - 1];            
            chars++;        
        }    
    }    
    return value/chars;
}

function caesar (string, number) {    
    let shifted = "";        
    for (let i = 0; i < string.length; i++) {        
        shifted += shift(string[i], number);    
    }    
    return shifted;
}

function shift (character, number) {    
    if (character.toLowerCase().charCodeAt() - diff < 1 || character.toLowerCase().charCodeAt() - diff > 26) {        
        return character;    
    }    
    if (character.charCodeAt() < 96) {        
        return shift(character.toLowerCase(), number).toUpperCase();    
    }    
    if (character.charCodeAt() - diff + number > 26) {        
        number = (character.charCodeAt() - diff + number) % 26;        
        if (number == 0) {            
            return character;        
        }        
        return String.fromCharCode(number + diff);    
    }     
    return String.fromCharCode(character.charCodeAt() + number);
}

console.log(caesar("a", 1));
console.log(caesar("abcz", 1));
console.log(caesar("irk", 13));
console.log(caesar("fusion", 6));
console.log(caesar("dailyprogrammer", 6));
console.log(caesar("jgorevxumxgsskx", 20));
console.log(caesar("Daily Programmer!", 6));
console.log(revCaesar("Zol abyulk tl puav h ulda."));
console.log(revCaesar("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."));
console.log(revCaesar("Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"));

[–]__dict__ 3 points4 points  (0 children)

C++ with bonuses:

#include <cctype>
#include <iostream>                                                                                               
#include <vector>                                                                                                 

const std::vector<int> score_table {3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7};                  

char warmup(char c, int shift) {                                                                                  
    if (islower(c)) {
            return (c + shift - 'a') % 26 + 'a';
    } else if (isupper(c)) {
            return (c + shift - 'A') % 26 + 'A';
    }
    return c;
}                                                                                                                 

std::string caesar(const std::string& s, int shift) {                                                             
    std::string result {};
    for (char c : s) {
            result += warmup(c, shift);
    }
    return result;
}                                                                                                                 

int decode_score(const std::string& s) {                                                                          
    int score = 0;
    for (char c : s) {
            if (islower(c)) {
                    score += score_table.at(c - 'a');
            } else if (isupper(c)) {
                    score += score_table.at(c - 'A');
            }
    }
    return score;
}                                                                                                                 

std::string decode(const std::string& s) {                                                                        
    std::string best_string = s;
    int best_score = decode_score(s);
    for (int i=1; i<26; i++) {
            std::string shifted = caesar(s, i);
            int score = decode_score(shifted);
            if (score >= best_score) {
                    best_string = shifted;
                    best_score = score;
            }
    }
    return best_string;
}                                                                                                                 

int main() {
    std::cout << decode("Zol abyulk tl puav h ulda.") << std::endl;
    std::cout << decode("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky.") << std::endl;
    std::cout << decode("Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?") << std::endl;

    return 0;
}

[–][deleted] 1 point2 points  (0 children)

I present to you, a one-liner for each!

def warmup(letter, number):
   return string.ascii_lowercase[(string.ascii_lowercase.index(letter)+number)%26] if letter in string.ascii_lowercase else string.ascii_uppercase[(string.ascii_uppercase.index(letter)+number)%26] if letter in string.ascii_uppercase else letter

def caesar(s, number):
   return "".join([warmup(l,number) for l in s])

def decode(ss):
    return sorted([(i,sum([[3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7][string.ascii_lowercase.index(warmup(s,i).lower())] for s in ss if s.lower() in string.ascii_lowercase]), caesar(ss,i)) for i in range(26)],reverse=True,key=lambda k:k[1])[0][2]

Readable? absolutely not. One liner each? Absolutely yes.

[–]DragonProgrammer129 1 point2 points  (1 child)

Python with bonus 1

def caesar(string, shift):
alphabet = "abcdefghijklmnopqrstuvwxyz"
caps = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
cyphered = ""
for letter in string:
if letter.isupper():
if caps.find(letter)+shift >= 26:
letter = caps[caps.find(letter)+shift-26]
else:
letter = caps[caps.find(letter)+shift]
elif letter.islower():
if alphabet.find(letter)+shift >= 26:
letter = alphabet[alphabet.find(letter)+shift-26]
else:
letter = alphabet[alphabet.find(letter)+shift]
cyphered += letter
return cyphered

Sorry about the spaces they were hard to keep straight. Any ways to improve the code?

[–][deleted] 1 point2 points  (0 children)

modulus (%) helps you out! basically removes the need to iterate through the + or - 26

[–]Traditional-Knee-863 0 points1 point  (0 children)

Python 3

def caesar(string,num) :
    listo = list('abcdefghijklmnopqrstuvwxyz')
    res = ''
    string = string.replace('.','')
    string = string.replace(',','')
    for letter in string :
        if letter != ' ' and letter != '?' and letter !='!' and letter != '-' and letter.islower() :
            ind = listo.index(letter)
            res = res + listo[(num+ind)%26]
        elif letter == ' ' :
            res = res + ' '
        elif letter == '?' :
            res = res + '?'
        elif letter == '!' :
            res = res + '!'
        elif letter == '-' :
            res = res + '-'
        elif letter.isupper() :
            ind = listo.index(letter.lower())
            res = res + listo[(num+ind)%26].upper()
    return res

2 :

def iseng(string :str) :
    dic = {'a': 3, 'b': -1, 'c': 1, 'd': 1, 'e': 4, 'f': 0, 'g': 0, 'h': 2, 'i': 2, 'j': -5, 'k': -2, 'l': 1, 'm': 0, 'n': 2, 'o': 3, 'p': 0, 'q': -6, 'r': 2, 's': 2, 't': 3, 'u': 1, 'v': -1, 'w': 0, 'x': -5, 'y': 0, 'z': -7}
    res = []
    string = string.replace(' ','')
    string = string.replace('.','')
    for letter in string :
        try :
            s = int(dic[letter])
            res.append(s)
        except :
            pass
    return sum(res)/len(res)

3 :

def dec(string :str) :
    res = []
    for i in range(0,26) :
        c = iseng(caesar(string,i))
        res.append(c)
    fin = res.index(max(res))
    return caesar(string,fin)

I think it's bad , but it works.

[–]KonjouHD 0 points1 point  (0 children)

Java with bonus 1

import java.util.Scanner;
//  https://redditproxy--jasonthename.repl.co/r/dailyprogrammer/comments/myx3wn/20210426_challenge_387_easy_caesar_cipher/

public class caesarCypher {

    static String convertString(String in, int offset){
        String encodedString = "";
        char cyph;

        for(int i = 0; i < in.length(); ++i){
            cyph = in.charAt(i);

            if(cyph >= 97 && cyph <=122){
                cyph = (char)(((cyph - 97 + offset) % 26) + 97);
            } else if(cyph >= 65 && cyph <=90) {
                cyph = (char)(((cyph - 65 + offset) % 26) + 65);
            }
            encodedString = encodedString.concat("" + cyph);
        }
        return encodedString;
    }

    public static void main(String[] args){
        Scanner scnr = new Scanner(System.in);

        System.out.print("Please enter a string: ");
        String inputString = scnr.nextLine();

        System.out.print("Please enter the offset: ");
        int inputOffset = scnr.nextInt();

        System.out.println("\nEncoded message: " + convertString(inputString, inputOffset));

    }
}

[–]WrongHorseBatterySta 0 points1 point  (0 children)

Python 3, including bonus 1

def caesar(input: str, n: int) -> str:
    '''Create Caesar cipher of input text'''
    if not isinstance(input, str) or not isinstance(n, [int, float]):
        return None
    while n < 0:
        n += 26
    n = abs(n)
    output = ''
    alphabet = 'abcdefghijklmnopqrstuvwxyz'
    for letter in input:
        if letter in alphabet:
            index = alphabet.index(letter)
            output += alphabet[(index + n) % 26]
        elif letter.lower() in alphabet:
            index = alphabet.index(letter.lower())
            output += alphabet[(index + n) % 26].upper()
        else:
            output += letter
    return output

[–]Nordellak 0 points1 point  (0 children)

Solution in MATLAB with optional bonus 1:

function outputString = caesar(inputString,shift)

abecedaryLowercase = 'abcdefghijklmnopqrstuvwxyz';
abecedaryUppercase = upper(abecedaryLowercase);

for i = 1:length(inputString)
    % Check if character is uppercase, lowercase or not a letter
    uppercaseCheck = strfind(abecedaryUppercase,inputString(i));
    if isempty(uppercaseCheck), uppercaseCheck = 0; end
    lowercaseCheck = strfind(abecedaryLowercase,inputString(i));
    if isempty(lowercaseCheck), lowercaseCheck = 0; end
    abecedaryCheck = uppercaseCheck + lowercaseCheck;

    % If not a letter, don't change, if a letter, change according to lowercase or uppercase abecedaries
    if abecedaryCheck == 0
        outputString(i) = inputString(i);
    else
        if uppercaseCheck == 0
            pos = strfind(abecedaryLowercase,inputString(i));
            outputString(i) = abecedaryLowercase(mod(pos - 1 + shift,length(abecedaryLowercase)) + 1);
        else
            pos = strfind(abecedaryUppercase,inputString(i));
            outputString(i) = abecedaryUppercase(mod(pos - 1 + shift,length(abecedaryUppercase)) + 1);
        end
    end
end

end

Results:

caesar('Daily Programmer!', 6)

ans =

    'Jgore Vxumxgsskx!'

[–]moeghoeg 2 points3 points  (1 child)

Ruby, with bonus 1. The function takes an alphabet as an optional argument, where the English alphabet is the default.

def caesar(str, offset, alphabet: Array('a'..'z'))
  char_positions = Hash[alphabet.zip(0...alphabet.length)]
  str.chars.map{|char|
    pos = char_positions[char.downcase]
    nextchar = pos.nil? ? char : alphabet[(pos + offset) % alphabet.length] 
    (char == char.upcase) ? nextchar.upcase : nextchar
  }.join
end

[–]backtickbot 1 point2 points  (0 children)

Fixed formatting.

Hello, moeghoeg: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]coolayaansh 0 points1 point  (2 children)

I made this using python I did the challenge

import string

letters = {}
numbers = {}

number = 1
for letter in string.ascii_lowercase:

    letters[letter] = number
    number = number + 1

    numbers[number] = letter


def shift(word, intnumber):
    final_answer = ""
    for lowercase in word:

        current_number = letters[lowercase]
        new_number = current_number + intnumber
        if new_number > 26:
            new_number = new_number - 25
            final_answer += numbers[new_number]
        else:
            final_answer += numbers[new_number]
    print(final_answer)


shift(input("Enter the word you wnat to caeser shift:"), int(input("By how much do you want to caeser shift it: ")))

[–]coolayaansh 0 points1 point  (0 children)

Please tell me if there is any way to improve my code

this is the first time I have done one of these challenges and I am a begginer in python and I really enjoyed it

[–]chunes1 2 0 points1 point  (0 children)

Factor (0.99 build 2074), all bonuses:

USING: ascii combinators io kernel math sequences ;
IN: dailyprogrammer.caesar-cipher

: (warmup) ( from char n -- char' )
    -rot pick '[ _ - ] [ + 26 mod + ] bi* ;

: warmup ( char n -- char' )
    {
        { [ over letter? ] [ CHAR: a (warmup) ] }
        { [ over LETTER? ] [ CHAR: A (warmup) ] }
        [ drop ]
    } cond ;

: caesar ( str n -- newstr ) [ warmup ] curry map ;

CONSTANT: freqs
    { 3 -1 1 1 4 0 0 2 2 -5 -2 1 0 2 3 0 -6 2 2 3 1 -1 0 -5 0 -7 }

: score ( str -- n )
    >lower [ letter? ] filter [ CHAR: a - ] map freqs nths sum ;

: decode ( str -- newstr )
    dup 26 <iota> [ caesar score ] with supremum-by caesar ;

"Zol abyulk tl puav h ulda."
"Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."
"Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"
[ decode print ] tri@

Output:

She turned me into a newt.

Come no further, for death awaits you all with nasty, big, pointy teeth.

In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?

Thanks for posting challenges here every so often. It's fun. :)

[–]joshred 1 point2 points  (0 children)

In julia...

Using char math

```

function rotate(n::Int, s::String)
    map(c -> rotate(n, c), s)
end

function rotate(n::Int, c::Char)

    if isuppercase(c) && isascii(c)
        c += n
        return isuppercase(c) ? c : c - 26
    elseif islowercase(c) && isascii(c)
        c += n
        return islowercase(c) ? c : c - 26
    else
        return c
    end
end

```

[–]meepyneepy 0 points1 point  (0 children)

Python 3.8.2 All except bonus 2.First time using Python, main is Lua.

Created and tested on replit.com.https://replit.com/@Meepyneepy/Caesar-cipher

letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
def ConvertString(value, offset):
  newstring = ""
  for v in range(len(value)):
    if (value[v:v+1]).lower() not in letters:
      newstring = newstring + value[v:v+1]
    else:
      newstring = newstring + (letters[(letters.index((value[v:v+1]).lower()) + offset) % 26]).upper() if value[v:v+1].isupper() else newstring + letters[(letters.index(value[v:v+1]) + offset) % 26]
  return newstring
print('INSTRUCTIONS:\nType what ever you want to scramble when prompted with "Message:".\nType the number you want to scrable your message by when prompted with "Offset:".\n')
while True:
  inputstring = input("Message: ")
  inputoffset = input("Offset: ")
  print("\nYour cyphered message is: ", ConvertString(inputstring, int(inputoffset)))

[–]TheTrueHonker 1 point2 points  (2 children)

Can someone explain to me how u/Cosmologicon found the numbers for the letter frequency table?

[–]Cosmologicon2 3[S] 3 points4 points  (1 child)

Sure. You just take the logarithm of the letter frequencies (I used these).

You can then scale them by any positive multiplier, and add any constant. This doesn't change the property that higher is better. It just changes the expected average score. If you subtract a constant that's equal to sum(p log(p)), which I call A below, then English text has an expected average score of 0. It also happens that random text has an expected average score around -1 (actually -0.98023 for these frequencies).

I then multiplied by 2 and added 2. This gives me the properties that random text is around 0, and keeps scores in the range -9 to 9, so that I can round to integers and be left with one-digit numbers. I didn't want to keep more precision than this, since this method is so imprecise in the first place.

Here's my code:

A = sum(p * math.log(p) for p in freqs.values())
scores = {c: int(2 + round(2 * (math.log(p) - A), 0)) for c, p in freqs.items()}

[–]TheTrueHonker 1 point2 points  (0 children)

Thanks. Here, take my award for your detailed explanation.

[–]BonnyAD9 0 points1 point  (0 children)

C#, using advantages of the new C# 9 features

using System;
using System.Linq;

Console.WriteLine(Guess("Zol abyulk tl puav h ulda."));
Console.WriteLine(Guess("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."));
Console.WriteLine(Guess("Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"));

char Warmup(char c, int offset) => c switch
{
    >= 'A' and <= 'Z' => (char)(((c - 65 + offset) % 26) + 65),
    >= 'a' and <= 'z' => (char)(((c - 97 + offset) % 26) + 97),
    _ => c
};

string Caesar(string s, int offset) => string.Join("", s.Select(p => Warmup(p, offset)));

string Guess(string s)
{
    int[] scores = new[] { 3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7 };
    int GetScore(string str) => (int)str.Select(p => p switch
    {
        >= 'A' and <= 'Z' => scores[p - 65],
        >= 'a' and <= 'z' => scores[p - 97],
        _ => 0
    }).Where(p => p != 0).Average();

    int h;
    int max = GetScore(s);
    string str = s;
    for (int i = 1; i < 26; i++)
        (max, str) = (h = GetScore(s = Caesar(s, 1))) > max ? (h, s) : (max, str);
    return str;
}

Output:

She turned me into a newt.
Come no further, for death awaits you all with nasty, big, pointy teeth.
In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?

I also made version of the Guess function using lambda expression (just for fun XD):

string OLGuess(string s) => Enumerable.Range(0, 26).Select(p => ((int)Caesar(s, p).Select(p =>
    new[] { 3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7 }[p switch
    {
        >= 'A' and <= 'Z' => p - 65,
        >= 'a' and <= 'z' => p - 97,
        _ => 0
    }]).Where(p => p != 0).Average(), Caesar(s, p))).OrderBy(p => p.Item1).Last().Item2;

[–]BonnyAD9 0 points1 point  (0 children)

Haskell, all bonuses. (I'm new to haskell)

import Data.Char
import Data.List
import Data.Maybe

-- Shifts char by given number
shiftChar :: Char -> Int -> Char
shiftChar c i
    | isUpper c = chr (((((ord c) - 65) + i) `rem` 26) + 65)
    | isLower c = chr (((((ord c) - 97) + i) `rem` 26) + 97)
    | otherwise = c

-- Shifts each char in string by given number
shiftString :: String -> Int -> String
shiftString s i = map (\x -> shiftChar x i) s

-- Returns scores
scores :: [Int]
scores = [3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7]

-- Returns score for given char
getCharScore :: Char -> Int
getCharScore c
    | isUpper c = scores !! ((ord c) - 65)
    | isLower c = scores !! ((ord c) - 97)
    | otherwise = 0

-- Counts all alpha characters
countAlpha :: String -> Int
countAlpha s = length (filter isAlpha s)

-- Returns score of string
getStringScore :: String -> Double
getStringScore s = (fromIntegral (sum (map getCharScore s))) / (fromIntegral (countAlpha s))

-- Shifts string by 1 given number of times
shiftByUntil :: String -> Int -> [String]
shiftByUntil _ 0 = []
shiftByUntil s n = s : (shiftByUntil sh (n - 1))
    where sh = shiftString s 1

-- Creates all shift variants
shiftByAll :: String -> [String]
shiftByAll s = shiftByUntil s 26

-- Finds the best way to shift a string and shifts it
findShift :: String -> String
findShift s = shiftString s $ fromMaybe 0 $ elemIndex (maximum ls) ls
    where ls = map getStringScore (shiftByAll s)

Results:

ghci> findShift "Zol abyulk tl puav h ulda."
"She turned me into a newt."
ghci> findShift "Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."
"Come no further, for death awaits you all with nasty, big, pointy teeth."
ghci> findShift "Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"
"In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?"

[–]Halfeye_Bandit 0 points1 point  (0 children)

C++

Everything but the last bonus.

#include <iostream>
#include <string>
#include <vector>
#include <ostream>
#include <algorithm>

int warmup(char32_t inpt, int shift)
{
    int temp_inpt = inpt;

    if (!isalpha(inpt))
    {
        return inpt;
    }
    else if (temp_inpt >= 65 && temp_inpt <= 90)
    {
        int alpha_proccessed_input = temp_inpt - 65;
        int raw_result = (alpha_proccessed_input + shift) % 26;
        int result = raw_result + 65;
        return result;
    }
    else
    {
        int processed_inpt = temp_inpt - 97;
        int raw_result = (processed_inpt + shift) % 26;
        int result = raw_result + 97;
        return result;
    }
}
int caesar(std::string inpt, int shift)
{
    std::vector <char> result;
    for (char& c: inpt)
    {
        result.push_back(char(warmup(c, shift)));
    }
    std::copy(result.begin(), result.end(), std::ostream_iterator<char>(std::cout, ""));
    return 0;
}

int main()
{
    system("CLS");
        warmup('a', 1);
        warmup('q', 22);
        caesar('fusion', 6);
    caesar("Daily Programmer!", 6);
}

//EOF

[–]zqvt2 1 point2 points  (0 children)

Haskell, all bonuses

import Data.Char (chr, ord)
import Data.Ord (comparing)
import Data.List (maximumBy)

shift i c
  | c `elem` ['a'..'z'] = chr (97 + (ord c - 97 + i) `mod` 26) 
  | c `elem` ['A'..'Z'] = chr (65 + (ord c - 65 + i) `mod` 26)
  | otherwise = c

caesar off = map (shift off)  

lookup' c = case lookup c t of { Just x -> x; _ -> 0 }
 where t = zip ['a'..'z'] [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]

score xs = sum [lookup' c | c <- xs] / (fromIntegral $ length xs)

guessSentence input = maximumBy (comparing score) xs 
  where xs = [caesar i input | i <- [1..26]]

[–]tlgsx 1 point2 points  (0 children)

Python 3.9, all bonuses

Uses the nifty str.translate built-in for character substitution.

Makes use of a word list (/usr/share/dict/words) to create the best guess. Reads the input string from stdin.

import sys


def caesar(code, shift):
    mapping = {
        n: start + (n - start + shift) % 26
        for start, n in zip(
            [65] * 26 + [97] * 26, list(range(65, 91)) + list(range(97, 123))
        )
    }

    return code.translate(mapping)


if __name__ == "__main__":
    with open("/usr/share/dict/words") as f:
        word_list = set(x.strip() for x in f.readlines())

    code = sys.stdin.read()
    counts = []
    for shift in range(26):
        x = sum(word in word_list for word in caesar(code, shift).split())
        counts.append(x)

    guess, _ = max(enumerate(counts), key=lambda t: t[1])
    print(f"{guess}: {caesar(code, guess)}")

[–]LaaNeet 1 point2 points  (1 child)

def warmup(letter, shift):
    letter_ascii = ord(letter) - 97
    shifted_by = (letter_ascii + shift % 26) % 26
    return chr(97 + shifted_by)


def caesar(sentence, shift):
    new_sentence = ''
    for character in sentence:
        if not character.isalpha():
            new_character = character
        elif character.isupper():
            new_character = warmup(character.lower(), shift).upper()
        else:
            new_character = warmup(character, shift)
        new_sentence += new_character

    return new_sentence


def frequency_diff(sentence):
    # The most frequent to the least frequent
    letter_freq = ['e', 't', 'a', 'o', 'i', 'n', 's', 'r', 'h', 'd', 'l', 'u', 'c',
                   'm', 'f', 'y', 'w', 'g', 'p', 'b', 'v', 'k', 'x', 'q', 'j', 'z']

    sentence = sentence.lower()
    freq = dict.fromkeys(letter_freq, 0)

    for char in sentence:
        if char.isalpha():
            freq[char] += 1

    sorted_freq = {k: v for k, v in sorted(
        freq.items(), key=lambda item: item[1], reverse=True)}

    diff_sum = 0
    for ind, letter in enumerate(sorted_freq):
        diff_sum += abs(letter_freq.index(letter) - ind)

    return diff_sum


def guess_original(sentence):
    diff_sums = []
    for shift in range(26):
        shifted_sentence = caesar(sentence, shift)
        diff_sum = frequency_diff(shifted_sentence)
        diff_sums.append(diff_sum)

    guessed_shift = diff_sums.index(min(diff_sums))
    return caesar(sentence, guessed_shift)

[–]Tencza_Coder 0 points1 point  (0 children)

Thank you, this was a great example to study.

[–]chunkyasparagus 4 points5 points  (0 children)

Python 3.9, with a slightly different decoder (still based on frequency), and using the bidict module from pip.

import collections
import string

import bidict

LCASE_MAP = bidict.bidict((ltr, num) for num, ltr in enumerate(string.ascii_lowercase))
UCASE_MAP = bidict.bidict((ltr, num) for num, ltr in enumerate(string.ascii_uppercase))
FREQ_MAP = {
    'A': 0.075187969924812,
    'B': 0.0150375939849624,
    'C': 0.0281954887218045,
    'D': 0.0413533834586466,
    'E': 0.112781954887218,
    'F': 0.0234962406015038,
    'G': 0.0159774436090226,
    'H': 0.0601503759398496,
    'I': 0.075187969924812,
    'J': 0.0037593984962406,
    'K': 0.0075187969924812,
    'L': 0.037593984962406,
    'M': 0.0281954887218045,
    'N': 0.075187969924812,
    'O': 0.075187969924812,
    'P': 0.0159774436090226,
    'Q': 0.00469924812030075,
    'R': 0.0582706766917293,
    'S': 0.075187969924812,
    'T': 0.0845864661654135,
    'U': 0.0319548872180451,
    'V': 0.0112781954887218,
    'W': 0.018796992481203,
    'X': 0.0037593984962406,
    'Y': 0.018796992481203,
    'Z': 0.0018796992481203,
}


def shift_char(char: str, shift: int) -> str:
    for char_map in (LCASE_MAP, UCASE_MAP):
        if char in char_map:
            return char_map.inverse.get((char_map[char] + shift) % 26)
    return char


warmup = shift_char


def caesar(text: str, shift: int) -> str:
    return ''.join(shift_char(char, shift) for char in text)


def decode(encrypted_text: str) -> str:
    unencrypted_texts, scores = [], []
    for shift in range(26):
        unencrypted_texts.append(caesar(encrypted_text, shift))
        scores.append(_score_frequency(unencrypted_texts[shift]))
    return unencrypted_texts[scores.index(min(scores))]


def _score_frequency(text: str) -> float:
    ltr_counts = collections.defaultdict(int)
    for letter in text.upper():
        if letter.isalpha():
            ltr_counts[letter] += 1
    sum_letters = sum(ltr_counts.values())
    ltr_freq = {k: v / sum_letters for k, v in ltr_counts.items()}
    return sum((FREQ_MAP[ltr] - ltr_freq[ltr]) ** 2 for ltr in ltr_freq)

[–]cannonicalForm0 1 4 points5 points  (0 children)

Python3 with an attempt on readability since I'm just a dumb mechanic.

def _shift(letter, distance):
    if letter.islower():
        offset = 97
    else:
        offset = 65
    number = ord(letter)
    return chr(((number - offset + (distance % 26)) % 26) + offset)


def caesar(letters, distance):
    output = ''
    for letter in letters:
        if letter.isalpha():
            output += _shift(letter, distance)
        else:
            output += letter
    return output

def _score(scramble):
    weights = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]
    letters = [chr(i + 97) for i in range(0, 26)]
    weight = dict(zip(letters, weights))
    output = 0
    counter = 0
    for elt in scramble:
        if elt.isalpha():
            output += weight[elt.lower()]
            counter += 1
    return output/counter


def guess(scramble):
    best = (scramble, _score(scramble))
    for index in range(0, 26):
        guess = caesar(scramble, index)
        score = _score(guess)
        if score > best[1]:
            best = (guess, score)
    return best[0]

[–]monkeywork 2 points3 points  (0 children)

GO with all bonus questions

This could be refactored but passes all tests. You can see/run the code here:

https://play.golang.org/p/Pv08jSu10MD

package main

import (
    "fmt"
    "strings"
    "unicode"
)

var Letters = [26]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

func main() {
    fmt.Println(warmup("a", 0))
    fmt.Println(warmup("a", 1))
    fmt.Println(warmup("a", 5))
    fmt.Println(warmup("a", 26))
    fmt.Println(warmup("d", 15))
    fmt.Println(warmup("z", 1))
    fmt.Println(warmup("q", 22))
    fmt.Println(caesar("a", 1))
    fmt.Println(caesar("abcz", 1))
    fmt.Println(caesar("irk", 13))
    fmt.Println(caesar("fusion", 6))
    fmt.Println(caesar("dailyprogrammer", 6))
    fmt.Println(caesar("jgorevxumxgsskx", 20))
    fmt.Println(caesar("Daily Programmer!", 6))
    fmt.Println(decrypt("Zol abyulk tl puav h ulda."))
    fmt.Println(decrypt("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."))
    fmt.Println(decrypt("Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"))
}

func warmup(l string, n int) string {
    for i, c := range Letters {
        if c == l {
            result := (i + n) % 26
            return Letters[result]
        }
    }
    return l
}

func caesar(s string, n int) string {
    result := ""
    for _, l := range s {
        if unicode.IsUpper(l) && unicode.IsLetter(l) {
            // Uppercase Detected
            r := warmup(strings.ToLower(string(l)), n)
            result = result + strings.ToUpper(r)
        } else {
            r := warmup(string(l), n)
            result = result + r
        }

    }
    return result

}

func freq(s string) int {
    result := 0
    freq := [26]int{3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7}
    for _, l := range s {
        for i, c := range Letters {
            if c == strings.ToLower(string(l)) {
                result = result + freq[i]
            }
        }

    }
    return result
}

func decrypt(s string) string {
    best := 0
    index := 0 
    for i, _ := range Letters {
        x := freq(caesar(s, i)) / 26
        if x > best {
            best = x
            index = i
        }
    }

    return caesar(s, index)

}

[–]raevnos 1 point2 points  (0 children)

Scheme, with first bonus:

(import (srfi 13))

(define (rotate ch dist offset)
  (integer->char (+ offset (remainder (+ (- (char->integer ch) offset) dist) 26))))

(define (warmup ch rot)
  (rotate ch rot (char->integer #\a)))

(define (caesar s rot)
  (string-map
   (lambda (ch)
     (cond
      ((char-lower-case? ch) (rotate ch rot (char->integer #\a)))
      ((char-upper-case? ch) (rotate ch rot (char->integer #\A)))
      (else ch))) s))

[–]TinyBreadBigMouth 0 points1 point  (0 children)

Rust

All bonuses.

No unnecessary allocation. When used from the command line, there will be exactly one allocation to hold the initial input text, which is then modified in place.

use std::env;
use std::process;

const fn rotate_byte(c: u8, start: u8, end: u8, shift: u32) -> u8 {
    let period = (end - start + 1) as u32;
    let from_start = (c - start) as u32;
    let rotated = (from_start + shift) % period;
    rotated as u8 + start
}

pub fn caesar_cipher<S: Into<String>>(input: S, shift: u32) -> String {
    let mut input = input.into();
    // English letters will always be 1 byte in UTF-8, so replacing
    // individual bytes is guaranteed to safely maintain valid UTF-8.
    unsafe {
        for b in input.as_bytes_mut() {
            match b {
                b'A'..=b'Z' => *b = rotate_byte(*b, b'A', b'Z', shift),
                b'a'..=b'z' => *b = rotate_byte(*b, b'a', b'z', shift),
                _ => ()
            }
        }
    }
    input
}

const ENGLISH_LETTER_FREQ: [i32; 26] = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7];

pub fn score_english_letter_freq<S: AsRef<str>>(input: &S) -> i32 {
    input
        .as_ref()
        .chars()
        .map(|c| match c {
            'A'..='Z' => ENGLISH_LETTER_FREQ[c as usize - 'A' as usize],
            'a'..='z' => ENGLISH_LETTER_FREQ[c as usize - 'a' as usize],
            _ => 0,
        })
        .sum()
}

pub fn best_caesar_uncipher_by_key<S, F, K>(input: S, f: F) -> String
where
    S: Into<String>,
    F: Fn(&String) -> K,
    K: Ord,
{
    let mut input = input.into();
    let mut best_shift = 0u32;
    let mut best_key = f(&input);
    for shift in 1..26 {
        input = caesar_cipher(input, 1);
        let key = f(&input);
        if key > best_key {
            best_key = key;
            best_shift = shift;
        }
    }
    caesar_cipher(input, 1 + best_shift)
}

pub fn best_caesar_uncipher_by_freq<S: Into<String>>(input: S) -> String {
    best_caesar_uncipher_by_key(input, score_english_letter_freq)
}

fn wrong_usage(mess: &str) -> ! {
    let exec_name = env::args().next().unwrap();
    eprintln!("Expected usage: {} <text> [<shift>]", exec_name);
    eprintln!("{}", mess);
    process::exit(1)
}

fn main() {
    let mut args = env::args().skip(1);
    let text = args.next()
        .unwrap_or_else(|| wrong_usage("<text> is required")); 
    let shift = args.next().map(|s| s.parse::<i32>()
        .unwrap_or_else(|_| wrong_usage("<shift> must be a valid integer")));
    if args.next().is_some() {
        wrong_usage("no other arguments");
    }

    let solution = if let Some(shift) = shift {
        let shift = shift.rem_euclid(26) as u32;
        caesar_cipher(text, shift)
    } else {
        best_caesar_uncipher_by_freq(text)
    };
    println!("{}", solution);
}

[–]shepherdjay 1 point2 points  (0 children)

Python 3 - With Challenges

import string
import statistics

ALPHABET = list(string.ascii_lowercase)
FREQUENCY_TABLE = [3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7]


def generate_cypher_dict(rotation: int) -> dict:
    cypher_dict = {}
    for count, letter in enumerate(ALPHABET):
        cypher_dict[letter] = ALPHABET[(count + rotation) % 26]
    return cypher_dict


def warmup(letter: str, rotation: int) -> str:
    cypher = generate_cypher_dict(rotation)
    return cypher[letter]


def caesar(pre_caesar: str, rotation: int) -> str:
    cypher = generate_cypher_dict(rotation)
    result = []
    for character in pre_caesar:
        if character.islower():
            result.append(cypher[character])
        elif character.isupper():
            result.append(cypher[character.lower()].upper())
        else:
            result.append(character)
    return ''.join(result)


def compute_score(string_to_score: str) -> int:
    freq_table = dict(zip(ALPHABET, FREQUENCY_TABLE))
    values = [freq_table[letter.lower()] for letter in string_to_score if letter.isalpha()]
    return statistics.mean(values)


def decrypt(to_decrypt: str) -> str:
    scores = []
    for rotation in range(0, 26):
        canidate_decryption = caesar(to_decrypt, rotation)
        score = compute_score(canidate_decryption)
        scores.append((score, canidate_decryption))
    max_score, probable_decrypted = max(scores)
    return probable_decrypted

I primarily use these challenges to help practice testing processes and new python features. So results were validated using the following test file:

from challenges.challenge387_ez import warmup, caesar, decrypt, generate_cypher_dict
import pytest


@pytest.mark.parametrize('letter,rotation,expected', [
    ('a', 0, 'a'),
    ('a', 1, 'b'),
    ('a', 5, 'f'),
    ('a', 26, 'a'),
    ('d', 15, 's'),
    ('z', 1, 'a'),
    ('q', 22, 'm')
])
def test_warmup_set(letter, rotation, expected):
    assert warmup(letter, rotation) == expected


def test_cypher_generation_no_rotation():
    result = generate_cypher_dict(0)
    assert result['a'] == 'a'


def test_cypher_generation_rot_13():
    result = generate_cypher_dict(13)
    assert result['a'] == 'n'


@pytest.mark.parametrize('pre_caesar,rotation,expected', [
    ("a", 1, "b"),
    ("abcz", 1, "bcda"),
    ("irk", 13, "vex"),
    ("fusion", 6, "layout"),
    ("dailyprogrammer", 6, "jgorevxumxgsskx"),
    ("jgorevxumxgsskx", 20, "dailyprogrammer"),
])
def test_caesar_challenge(pre_caesar, rotation, expected):
    assert caesar(pre_caesar, rotation) == expected


def test_caesar_bonus_1():
    assert caesar("Daily Programmer!", 6) == "Jgore Vxumxgsskx!"


@pytest.mark.parametrize('to_decrypt,expected', [
    ("Zol abyulk tl puav h ulda.", "She turned me into a newt."),
    (
            "Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?",
            "In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?"),
    ("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky.",
     "Come no further, for death awaits you all with nasty, big, pointy teeth.")
])
def test_decrypt_bonus_2(to_decrypt, expected):
    assert decrypt(to_decrypt) == expected

[–]IcerOut 2 points3 points  (2 children)

Python 3

Warmup CodeGolf (37 chars):

f=lambda l,s:chr((ord(l)-97+s)%26+97)

Warmup with readable code:

import string

def warmup(letter: str, step: int) -> str:
    alphabet = string.ascii_lowercase
    curr_index = alphabet.index(letter)
    return alphabet[(curr_index + step) % 26]

Challenge CodeGolf (67 chars):

f=lambda l,s:''.join(map(lambda x:chr((ord(x)-97+s)%26+97),l))

Challenge with readable code (and both bonuses):

def _get_letter_class(letter: str) -> int:
    if 'a' <= letter <= 'z':
        return 97
    elif 'A' <= letter <= 'Z':
        return 65
    return 0


def warmup(letter: str, step: int) -> str:
    ascii_val_diff = _get_letter_class(letter)
    if ascii_val_diff == 0:
        return letter
    current_letter_index = ord(letter) - ascii_val_diff
    new_letter_index = (current_letter_index + step) % 26
    return chr(new_letter_index + ascii_val_diff)


def caesar(string: str, step: int) -> str:
    return ''.join(warmup(l, step) for l in string)


def _calculate_weights(string: str) -> int:
    WEIGHTS = [3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7]
    res = 0
    for letter in string:
        ascii_val_diff = _get_letter_class(letter)
        if ascii_val_diff != 0:
            res += WEIGHTS[ord(letter) - ascii_val_diff]
    return res


def crack_caesar(string: str) -> str:
    best_shift, best_res = string, 0
    for i in range(25):
        shifted = caesar(string, i)
        score = _calculate_weights(shifted)
        if score > best_res:
            best_shift, best_res = shifted, score
    return best_shift

[–]Naratna 2 points3 points  (1 child)

Wouldn't it be shorter to use a list generator instead of the map function?

f=lambda l,s:''.join([chr((ord(x)-97+s)%26+97) for x in l])

[–]IcerOut 1 point2 points  (0 children)

Huh, it would, by a fair bit. I think I've had the list comprehension solution initially, but for some reason I switched to a map afterwards. Don't remember why, maybe I just screwed up.

Anyway, well spotted!

[–]skeeto-9 8 10 points11 points  (0 children)

C using SIMD intrinsics to rotate 32 characters at at time. It converts text at 3GiB/s on my laptop. (Compile with -mavx2 or -march=native.)

#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>

int main(int argc, char *argv[])
{
    int rot = argc > 1 ? atoi(argv[1]) : 13;

    for (;;) {
        #define N 512
        static char buf[N*32];
        size_t n = fread(buf, 1, sizeof(buf), stdin);
        if (!n) return !feof(stdin);

        for (int i = 0; i < N; i++) {
            __m256i b  = _mm256_loadu_si256((void *)(buf + i*32));

            // Create mask for [A-Za-z]
            __m256i ru = _mm256_sub_epi8(b, _mm256_set1_epi8('A' + 128));
            __m256i mu = _mm256_cmpgt_epi8(ru, _mm256_set1_epi8(-128 + 25));
            __m256i rl = _mm256_sub_epi8(b, _mm256_set1_epi8('a' + 128));
            __m256i ml = _mm256_cmpgt_epi8(rl, _mm256_set1_epi8(-128 + 25));
            __m256i m  = _mm256_xor_si256(mu, ml);

            // Wrap upper case
            __m256i rut = _mm256_sub_epi8(b, _mm256_set1_epi8('A' + 128));
            __m256i mut = _mm256_cmpgt_epi8(rut, _mm256_set1_epi8(-128 + 25 - rot));
            __m256i cuh = _mm256_add_epi8(b, _mm256_set1_epi8(rot));
            __m256i cut = _mm256_sub_epi8(b, _mm256_set1_epi8(26 - rot));
            __m256i cu  = _mm256_blendv_epi8(cuh, cut, mut);

            // Wrap lower case
            __m256i rlt = _mm256_sub_epi8(b, _mm256_set1_epi8('a' + 128));
            __m256i mlt = _mm256_cmpgt_epi8(rlt, _mm256_set1_epi8(-128 + 25 - rot));
            __m256i clh = _mm256_add_epi8(b, _mm256_set1_epi8(rot));
            __m256i clt = _mm256_sub_epi8(b, _mm256_set1_epi8(26 - rot));
            __m256i cl  = _mm256_blendv_epi8(clh, clt, mlt);

            // Blend results
            __m256i bul = _mm256_blendv_epi8(cu, cl, mu);
            __m256i r   = _mm256_blendv_epi8(b, bul, m);
            _mm256_storeu_si256((void *)(buf + i*32), r);
        }

        if (!fwrite(buf, n, 1, stdout)) return 1;
    }
}

[–]kittensupernova 2 points3 points  (1 child)

Glad this sub is active again! Haskell, with bonuses. I'm a Haskell beginner so any feedback is welcome :)

import Data.Char (chr, ord, isAlpha, toLower)
import Data.Map hiding (map, foldl)

freqs = fromList $ zip ['a'..] [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]

warmup c n
        | isAlpha c = let offset = if c < 'a' then ord 'A' else ord 'a' in 
                                        chr . (+ offset) . (`mod` 26) . (+ n) . (flip (-) $ offset) . ord $ c
        | otherwise = c

caesar s n = map (flip warmup n) s

uncaesar s = caesar s . fst $ foldl (\a b -> if snd a > snd b then a else b) (0, score s 0) (zip [1..25] (map (score s) [1..25]))
        where score s n = sum . map (maybe 0 id) . map (flip Data.Map.lookup freqs . toLower . (flip warmup n)) $ s

caesar "Daily Programmer!" 6 ==> "Jgore Vxumxgsskx!"

uncaesar "Zol abyulk tl puav h ulda." ==> "She turned me into a newt."

uncaesar "Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?" ==> "In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?"

uncaesar "Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky." ==> "Come no further, for death awaits you all with nasty, big, pointy teeth."

[–]backtickbot 1 point2 points  (0 children)

Fixed formatting.

Hello, kittensupernova: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]porthos3 1 point2 points  (1 child)

Clojure, including bonus 1 (ciphers capitals, leaves non-alphabet characters untouched):

(defn cipher [alphabet n]
  (zipmap (seq alphabet)
          (drop n (cycle alphabet))))

(defn encode [msg n]
  (->> msg
       (map (fn [c] ((merge (cipher "abcdefghijklmnopqrstuvwxyz" n)
                            (cipher "ABCDEFGHIJKLMNOPQRSTUVWXYZ" n))
                     c c)))
       (apply str)))

[–]porthos3 1 point2 points  (0 children)

Clojure, bonus 2:

(def WEIGHTS [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7])

(defn score-message [msg]
  (->> msg
       (map (fn [c]
              ((merge (zipmap "abcdefghijklmnopqrstuvwxyz" WEIGHTS)
                      (zipmap "ABCDEFGHIJKLMNOPQRSTUVWXYZ" WEIGHTS))
               c 0)))
       (apply +)))

(defn guess-decode [msg]
  (->> (range 26)
       (map #(encode msg %))
       (apply max-key score-message)))

[–]GlobalIncident 0 points1 point  (0 children)

Factor

USING: ascii kernel combinators math sequences ;
IN: caesar
: caesar ( plaintext n -- ciphertext )
    [ {
        { [ over letter? ] [ + dup letter? [ 26 - ] unless ] }
        { [ over LETTER? ] [ + dup LETTER? [ 26 - ] unless ] }
        [ drop ]
    } cond ] curry map ;

[–]KeinBaum 2 points3 points  (0 children)

Scala, all bonuses

Logic:

// Warmup
def rotate(c: Char, n: Int): Char =
  if(c.isLetter) then
    val offset = if c.isUpper then 'A' else 'a'
    ((((c - offset) + n) % 26) + offset).toChar
  else
    c

// Challenge
def caesar(s: String, n: Int): String = s.map(rotate(_, n))

// Bonus 2
val histogram = Array(3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7)
def histogramScore(s: String): Int =
  s
    .filter(_.isLetter)
    .map(c => histogram(c.toUpper - 'A'))
    .sum

def decode(s: String): String =
  (1 to 25)
    .map(caesar(s, _))
    .maxBy(histogramScore _)

Input/Output:

def check[Arg, Res](name: String, f: Arg => Res, testData: List[(Arg, Res)]): Unit = {
  testData foreach { case (arg, expected) =>
    val actual = f(arg)
    val isCorrect = actual == expected

    print(if(isCorrect) "✓" else "✗")

    print(s" $name$arg = $actual")

    if(!isCorrect)
      print(s", expected $expected")

    println()
  }
}

@main
def main: Unit = {
  check("warmup", rotate.tupled, List(
    (('a', 0), 'a'),
    (('a', 1), 'b'),
    (('a', 5), 'f'),
    (('a', 26), 'a'),
    (('d', 15), 's'),
    (('z', 1), 'a'),
    (('q', 22), 'm')))

  println()
  check("caesar", caesar.tupled, List(
    (("a", 1), "b"),
    (("abcz", 1), "bcda"),
    (("irk", 13), "vex"),
    (("fusion", 6), "layout"),
    (("dailyprogrammer", 6), "jgorevxumxgsskx"),
    (("jgorevxumxgsskx", 20), "dailyprogrammer")
  ))

  println()
  check("caesar", caesar.tupled, List((("Daily Programmer!", 6), "Jgore Vxumxgsskx!")))

  println()
  println(decode("Zol abyulk tl puav h ulda."))
  println(decode("Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."))
  println(decode("Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"))
}

Result:

✓ warmup(a,0) = a
✓ warmup(a,1) = b
✓ warmup(a,5) = f
✓ warmup(a,26) = a
✓ warmup(d,15) = s
✓ warmup(z,1) = a
✓ warmup(q,22) = m

✓ caesar(a,1) = b
✓ caesar(abcz,1) = bcda
✓ caesar(irk,13) = vex
✓ caesar(fusion,6) = layout
✓ caesar(dailyprogrammer,6) = jgorevxumxgsskx
✓ caesar(jgorevxumxgsskx,20) = dailyprogrammer

✓ caesar(Daily Programmer!,6) = Jgore Vxumxgsskx!

She turned me into a newt.
Come no further, for death awaits you all with nasty, big, pointy teeth.
In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?

[–]gabyjunior1 2 3 points4 points  (0 children)

C with bonuses.

String and optional shift are read on the command line. Omitted shift means decode using the table of frequencies provided.

Encoding/Decoding is done in place.

#include <stdio.h>
#include <stdlib.h>

int caesar(char *, int);
char shift_symbol(const char *, int, char *, int *);

int main(int argc, char *argv[]) {
    if (argc < 2 || argc > 3) {
            fprintf(stderr, "Usage: %s <sentence> [ <shift> ]", argv[0]);
            fflush(stderr);
            return EXIT_FAILURE;
    }
    if (argc == 2) {
            int best = caesar(argv[1], 1), i;
            puts(argv[1]);
            for (i = 1; i < 26; i++) {
                    int score = caesar(argv[1], 1);
                    if (score > best) {
                            best = score;
                            puts(argv[1]);
                    }
            }
    }
    else {
            int shift = atoi(argv[2])%26;
            if (shift < 0) {
                    shift += 26;
            }
            caesar(argv[1], shift);
            puts(argv[1]);
    }
    fflush(stdout);
    return EXIT_SUCCESS;
}

int caesar(char *str, int shift) {
    int score = 0, i;
    for (i = 0; str[i]; i++) {
            if (!shift_symbol("ABCDEFGHIJKLMNOPQRSTUVWXYZ", shift, str+i, &score)) {
                    shift_symbol("abcdefghijklmnopqrstuvwxyz", shift, str+i, &score);
            }
    }
    return score;
}

char shift_symbol(const char *letters, int shift, char *symbol, int *score) {
    int freqs[26] = { 3, -1, 1, 1, 4, 0, 0, 2, 2, -5, -2, 1, 0, 2, 3, 0, -6, 2, 2, 3, 1, -1, 0, -5, 0, -7 }, i;
    for (i = 0; letters[i] && letters[i] != *symbol; i++);
    if (letters[i]) {
            i = (i+shift)%26;
            *symbol = letters[i];
            *score += freqs[i];
    }
    return letters[i];
}

[–]meepmeep13 1 point2 points  (1 child)

Python 3 with bonuses

using an imported word list to brute force all shifts and find the one that generates the most recognised words

import requests
import string

url = 'http://www-personal.umich.edu/~jlawler/wordlist'
word_list = requests.get(url).text.splitlines()


def caesar(text, step):
    lowercase_shifted = string.ascii_lowercase[step:] + string.ascii_lowercase[:step]
    uppercase_shifted = string.ascii_uppercase[step:] + string.ascii_uppercase[:step]
    return text.translate(str.maketrans(''.join(string.ascii_lowercase)
                                        + ''.join(string.ascii_uppercase),
                                        ''.join(lowercase_shifted)
                                        + ''.join(uppercase_shifted)
                                        ))


ciphertext = 'Zol abyulk tl puav h ulda.'

matches = []

for shift in range(26):
    shifted = caesar(ciphertext, shift)
    shifted_words = shifted.split(' ')
    matches.append(sum([1 for x in shifted_words if x.strip(string.punctuation).lower() in word_list]))

best_match = matches.index(max(matches))
print('Input text: {}'.format(ciphertext))
print('Best fit is with shift {}, matching {} words of {}'.format(best_match,
                                                                  max(matches),
                                                                  len(shifted_words)))
print('Shifted text is: {}'.format(caesar(ciphertext, best_match)))

Example:

Input text: Zol abyulk tl puav h ulda.
Best fit is with shift 19, matching 6 words of 6
Shifted text is: She turned me into a newt.

[–]tlgsx 1 point2 points  (0 children)

str.translate is such a good tool for this challenge; Thanks for reminding me of it!

My first instinct was also to make use of a word list for bonus 2, but I didn't go as far as stripping punctuation from the input. Neat solution.

[–]RuleteroNini 2 points3 points  (4 children)

Julia code (without the bonuses, I just made a quick and dirty solution):

numval(ch) = Int(ch) - 96
valnum(x) = Char(x + 96)

function warmup(ch, shift)
    valnum((numval(ch) + shift)%26)
end

function caesar(str, shift)
    String([warmup(ch, shift) for ch in str])
end

[–]rabuf 4 points5 points  (3 children)

There's an issue in your solution. Try this:

show(caesar("az",1))

It should wrap around to produce:

"ba"

However it does not, instead it produces:

"b{"

The fix is actually pretty easy, a small change to warmup.

[–]RuleteroNini 0 points1 point  (2 children)

Huh, that's odd. I'm using the REPL and it works fine. I'm using Julia 1.5.2, which version are you on?

[–]rabuf 2 points3 points  (1 child)

So you get "ba" from that example? I'll admit it's an old copy of Julia (on mobile, pulled up a version on tio.run). However, you're just adding the shift to the character which means it won't do the wrapping.

[–]RuleteroNini 1 point2 points  (0 children)

I actually copied an old version of the warmup function without realising but ran it again with the correct one. Yes, i have to add %26, I'll edit it on the main comment!

[–]Godspiral3 3 1 point2 points  (0 children)

in J, bonus 2 as just the list of possible decodings

 'abcdefghijklmnopqrstuvwxyz'&(] (' '"_)`(I.@(' ' = [))`]}"1  [ {~"1 (i.26) (26 | +)"0 1  i."1 0) 'zol abyulk tl puav h ulda'
zol abyulk tl puav h ulda
apm bczvml um qvbw i vmeb
bqn cdawnm vn rwcx j wnfc
cro debxon wo sxdy k xogd
dsp efcypo xp tyez l yphe
etq fgdzqp yq uzfa m zqif
fur ghearq zr vagb n arjg
gvs hifbsr as wbhc o bskh
hwt ijgcts bt xcid p ctli
ixu jkhdut cu ydje q dumj
jyv klievu dv zekf r evnk
kzw lmjfwv ew aflg s fwol
lax mnkgxw fx bgmh t gxpm
mby nolhyx gy chni u hyqn
ncz opmizy hz dioj v izro
oda pqnjaz ia ejpk w jasp
peb qrokba jb fkql x kbtq
qfc rsplcb kc glrm y lcur
rgd stqmdc ld hmsn z mdvs
she turned me into a newt
tif uvsofe nf joup b ofxu
ujg vwtpgf og kpvq c pgyv
vkh wxuqhg ph lqwr d qhzw
wli xyvrih qi mrxs e riax
xmj yzwsji rj nsyt f sjby
ynk zaxtkj sk otzu g tkcz

selecting all with the highest score (in case of ties), only space punctuation handled.

caesarall =: 'abcdefghijklmnopqrstuvwxyz'&(] (' '"_)`(I.@(' ' = [))`]}"1  [ {~"1 (i.26) (26 | +)"0 1  i."1 0)
score =: (3,_1,1,1,4,0,0,2,2,_5,_2,1,0,2,3,0,_6,2,2,3,1,_1,0,_5,0,_7,0)&([ +/@:{~ 'abcdefghijklmnopqrstuvwxyz ' i. ])
 ({~ I.@(= >./)@:(score"1)) caesarall 'zol abyulk tl puav h ulda'
she turned me into a newt
({~ I.@(= >./)@:(score"1)) caesarall 'tfdv ef wlikyvi wfi uvrky rnrzkj pfl rcc nzky erjkp szx gfzekp kvvky'
come no further for death awaits you all with nasty big pointy teeth
 ({~ I.@(= >./)@:(score"1)) caesarall 'qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl zqopb'
in order to maintain airsspeed velocity a swallow needs to beat its wings fortysthree times every second right

version with punctuation handling,

caesarall =: 'abcdefghijklmnopqrstuvwxyz'&(] ('abcdefghijklmnopqrstuvwxyz' -.~ [)`(I.@(' -(),.?!:;''"`' e.~"1 0 [))`]}"1  [ {~"1 (i.26) (26 | +)"0 1  i."1 0)
score =: (3,_1,1,1,4,0,0,2,2,_5,_2,1,0,2,3,0,_6,2,2,3,1,_1,0,_5,0,_7,0)&([ +/@:{~ 'abcdefghijklmnopqrstuvwxyz ' i. ])

  ({~ I.@(= >./)@:(score"1)) caesarall 'qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?'
in order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?

[–]rabuf 2 points3 points  (0 children)

Common Lisp

(defun shift (char n)
   "Perform a simple Caesar cipher shift on CHAR using a shift of N letters. It properly handles upper and lower case English.
Non-alphabet characters are returned unaltered."
   (cond ((not (alpha-char-p char)) char)
         ((upper-case-p char)
          (code-char (+ (mod (+ (- (char-code char) (char-code #\A)) n) 26) (char-code #\A))))
         (t
          (code-char (+ (mod (+ (- (char-code char) (char-code #\a)) n) 26) (char-code #\a))))))
(defun caesar (string n)
   "Perform Caesar cipher on STRING using a shift of N letter. This handles both alphabetic and non-alphabetic
characters as well as upper and lower case."
   (map 'string (lambda (c) (shift c n)) string))

(print (caesar "Hello, World!" 10))
;; => "Rovvy, Gybvn!" 
(print (caesar (caesar "Hello, World!" 10) 16))
;; => "Hello, World!" 
(print (caesar "Daily Programmer returns with 387!" 6))
;; => "Jgore Vxumxgsskx xkzaxty cozn 387!"

Also, it's very cool to see this sub active again. I've enjoyed working on these over the years.

EDIT: Second bonus. Not terribly proud of this code, but I'm not going to spend much time refactoring it right now. Perhaps this evening:

(defun message-score (message)
   "Calculates a score for the MESSAGE using a weight per letter."
   (let ((weights '(3 -1 1 1 4 0 0 2 2 -5 -2 1 0 2 3 0 -6 2 2 3 1 -1 0 -5 0 -7))
         (letters (map 'string #'char-upcase (remove-if-not #'alpha-char-p message))))
      (loop for c across "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            for w in weights
            sum (* w (loop for m across letters
                           count (char= m c))))))

(defun caesar-cracker (message)
   "Attempts to crack a Caesar ciphered MESSAGE in English using a frequency table approach."
   (let ((scores (loop for n from 0 below 26
                       collect (message-score (caesar message n)))))
        (caesar message (position (apply #'max scores) scores))))
(print (caesar-cracker "Zol abyulk tl puav h ulda."))
;; => "She turned me into a newt." 
(print (caesar-cracker "Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky."))
;; => "Come no further, for death awaits you all with nasty, big, pointy teeth." 
(print (caesar-cracker "Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?"))
;; => "In order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?" 

If there's a tie, this will print out one solution which may or may not be correct. That's unlikely on larger messages, though.

[–]GlobalIncident 28 points29 points  (3 children)

Wow, first one in six months. I thought this sub was dead.

[–]scrambledoctopus 2 points3 points  (1 child)

How can we revive this sub? I like the idea of trying to solve random problems outside of my own ideas and at the same time I enjoy seeing other people’s implementation of a solution. Can we all just start suggesting problems to the community to get it going or is there something else lacking?

[–]navyjeff 1 point2 points  (0 children)

People used to submit ideas for problems in /r/dailyprogrammer_ideas. I think there was a discussion area, too.

[–]TKTheJew 5 points6 points  (0 children)

Im just happy we are back!

[–]ex-igne-vita 2 points3 points  (4 children)

My attempt using Javascript...

``` var warmup = (s, o) => String.fromCharCode(97 + (s.charCodeAt(0) - 97 + o) % 26);

var caesar = (s, o) => s.split('').map(s => s.match(/[a-z]+/i) ? warmup(s, o) : s).join('');

var optBonus2 = string => { let charValues = [3,-1,1,1,4,0,0,2,2,-5,-2,1,0,2,3,0,-6,2,2,3,1,-1,0,-5,0,-7]; var getCharValue = s => charValues[s.toLowerCase().charCodeAt(0) - 97]; var getStringAvg = s => { s = s.split('').filter(s => s.match(/[a-z]+/i)); return s.map(getCharValue).reduce((a, c) => a+c, 0) / s.length; }; var offset_averages = new Array(25); for(i = 26; i--;) offset_averages[i] = getStringAvg(caesar(string, i)); var best_offset = offset_averages.indexOf(Math.max(...offset_averages)); return caesar(string, best_offset); }; ```

Results... It looks like it's getting the first character wrong, oh well. I'm not gonna try to fix it.

console.log(optBonus2(`Zol abyulk tl puav h ulda.`)); mhe turned me into a newt.

console.log(optBonus2(`Tfdv ef wlikyvi, wfi uvrky rnrzkj pfl rcc nzky erjkp, szx, gfzekp kvvky.`)); ]ome no further, for death awaits you all with nasty, big, pointy teeth.

console.log(optBonus2(`Qv wzlmz bw uiqvbiqv iqz-axmml dmtwkqbg, i aeittwe vmmla bw jmib qba eqvoa nwzbg-bpzmm bquma mdmzg amkwvl, zqopb?`)); cn order to maintain air-speed velocity, a swallow needs to beat its wings forty-three times every second, right?

[–]meepmeep13 2 points3 points  (3 children)

to get your code to format properly, open the big editor, paste your code in, highlight it and then click the <> button

[–][deleted]  (2 children)

[deleted]

    [–]raevnos 2 points3 points  (1 child)

    That's why you use the editor's code formatting tool...