The ADFGX cipher was used by the German army in WWI. Write a program to encipher with it!

It works as follows:

1. Create a 5x5 Polybius square with a mixed alphabet. The polybias square is labled A D F G X along the top and left.
2. Generate the pairs, so A in its non-mixed position is AA, B is AD and so on.
3. Perform columnar transposition using the columnar key.
4. Output the ciphertext.

# Rules

• Your program should either define a function that accepts the arguments of the mixed alphabet and the columnar transposition key, in that order, or accept the alphabet/key as command-line arguments. You can also get input from STDIN.
• Standard loopholes apply.
• You can't use a pre-written columnar transposition library (or, for that matter, ADFGX) - i.e. no running something like import cipherpack.

# Scoring

This is , so shortest code (in bytes) wins!

# Test cases

My example runs used a failed source. I'll do some more later.

Run the Stack Snippet to generate a leaderboard.

/* Configuration */

var QUESTION_ID = 71997; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 50171; // This should be the user ID of the challenge author.

/* App */

return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

}

jQuery.ajax({
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
data.items.forEach(function(a) {
});
comment_page = 1;
}
});
}

jQuery.ajax({
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
data.items.forEach(function(c) {
if (c.owner.user_id === OVERRIDE_USER)
});
else process();
}
});
}

var SCORE_REG = /<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

function getAuthorName(a) {
return a.owner.display_name;
}

function process() {
var valid = [];

var body = a.body;
if(OVERRIDE_REG.test(c.body))
body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
});

var match = body.match(SCORE_REG);
if (match)
valid.push({
user: getAuthorName(a),
size: +match[2],
language: match[1],
});

});

valid.sort(function (a, b) {
var aB = a.size,
bB = b.size;
return aB - bB
});

var languages = {};
var place = 1;
var lastSize = null;
var lastPlace = 1;
valid.forEach(function (a) {
if (a.size != lastSize)
lastPlace = place;
lastSize = a.size;
++place;

.replace("{{NAME}}", a.user)
.replace("{{LANGUAGE}}", a.language)
.replace("{{SIZE}}", a.size)

var lang = a.language;
if (/<a/.test(lang)) lang = jQuery(lang).text();

languages[lang] = languages[lang] || {lang: a.language, user: a.user, size: a.size, link: a.link};
});

var langs = [];
for (var lang in languages)
if (languages.hasOwnProperty(lang))
langs.push(languages[lang]);

langs.sort(function (a, b) {
if (a.lang > b.lang) return 1;
if (a.lang < b.lang) return -1;
return 0;
});

for (var i = 0; i < langs.length; ++i)
{
var language = jQuery("#language-template").html();
var lang = langs[i];
language = language.replace("{{LANGUAGE}}", lang.lang)
.replace("{{NAME}}", lang.user)
.replace("{{SIZE}}", lang.size)
language = jQuery(language);
jQuery("#languages").append(language);
}

}
body { text-align: left !important}

width: 290px;
float: left;
}

#language-list {
width: 290px;
float: left;
}

font-weight: bold;
}

table td {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>

</tbody>
</table>
</div>
<div id="language-list">
<h2>Winners by Language</h2>
<table class="language-list">
<tr><td>Language</td><td>User</td><td>Score</td></tr>
<tbody id="languages">

</tbody>
</table>
</div>
<table style="display: none">
</tbody>
</table>
<table style="display: none">
<tbody id="language-template">
</tbody>
</table>

Note:

It is not necessary to split the output into groups of five.

• Wouldn't B in its non-mixed position be AD, not AB? – Doorknob Feb 13 '16 at 15:26
• Also, does it need to be case insensitive or can we assume all input is in uppercase? Could we have some test cases? – Doorknob Feb 13 '16 at 15:30
• Also, you never specified where the actual message to encipher comes in the input. Does it come first (before the alphabet and the key) or last (after them)? – Doorknob Feb 13 '16 at 15:33
• Do we need to separate the ciphertext into groups of five? – lirtosiast Feb 13 '16 at 16:07
• @Doorknob Yes, I've updated the question. I'll do some test cases when I'm on my PC. – bob Feb 13 '16 at 16:09

## Pyth, 26 bytes

seMhDC,Q.TcsXwz^"ADFGX"2lQ


For this, the second line (columnar key) needs to be in quotes, which is acceptable by default.

Try it here.

## Pyth, 36343332 31 bytes

JwseMhDC,J.Tcsm@^"ADFGX"2xzdwlJ

Jw                                assign (z, J) to 2 lines of input
m             w     map over each char of a 3rd input line...
xzd      find the index of this char in z
@                  index into ^^ with ^
s                    join groups of 2 ch. into one string
c                lJ   split ^ into groups of len(J) chars
.T                      transpose
C,J                        pair elems up with chars of J
hD                           sort by chars of J (the key)
eM                             get rid of the chars of J now
s                               join


Thanks to Thomas Kwa for a byte!

Sample run, using the example from Wikipedia:

llama@llama:~\$ pyth -c 'JwjdeMhDC,J.Tcsm@^"ADFGX"2xzdwlJ'
BTALPDHOZKQFVSNGJCUXMREWY
CARGO
ATTACKATONCE