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? Feb 13, 2016 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? Feb 13, 2016 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)? Feb 13, 2016 at 15:33
• Do we need to separate the ciphertext into groups of five? Feb 13, 2016 at 16:07
• @Doorknob Yes, I've updated the question. I'll do some test cases when I'm on my PC.
– user50171
Feb 13, 2016 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