Rétine , 45 43 octets
Le nombre d'octets suppose un codage ISO 8859-1.
O$#`.(?<=(.+))|¶
$.1
!`(?<=(¶)+.*)(?<-1>.)+
Le saut de ligne de tête est significatif. L'entrée et la sortie sont des listes terminées par saut de ligne de chaînes ASCII imprimables (notez que les deux ont un seul saut de ligne de fin).
Essayez-le en ligne!
Je savais depuis un moment que la transposition de blocs rectangulaires serait une douleur dans la rétine (alors que la transposition de carrés n'est pas trop mal), mais je n'ai jamais vraiment essayé. La première solution était en effet un énorme 110 octets de long, mais après plusieurs changements substantiels dans l'approche, les 45 octets résultants ne sont de loin pas aussi mauvais que je le pensais (mais quand même ...). L'explication suivra demain.
Explication
Étape 1: trier
O$#`.(?<=(.+))|¶
$.1
Cela fait le travail principal de réordonner les caractères dans l'entrée, mais cela finit par gâcher la séparation en lignes. Fait intéressant, si nous supprimons le |¶
, nous obtenons le code requis pour transposer une entrée carrée.
Les étapes de tri (indiquées par le O
) fonctionnent comme ceci: elles trouvent toutes les correspondances de l'expression rationnelle donnée (la chose après le `
), puis trient ces correspondances et les réinsèrent dans les endroits où les correspondances ont été trouvées. En fait, cette expression régulière correspond à chaque caractère: les sauts de ligne non via l' .(?<=(.*))
alternative et les sauts de ligne via le ¶
. Par conséquent, il trie tous les caractères de l'entrée. La partie la plus intéressante est ce qu'ils sont classés par .
L' $
option active un mode de "tri par", où chaque correspondance est remplacée par le modèle de substitution sur la deuxième ligne, qui est ensuite utilisé pour comparer les correspondances. De plus, le #
paramètre indique à Retina de convertir le résultat de la substitution en un entier et de comparer ces entiers (au lieu de les traiter comme des chaînes).
Donc, finalement, nous devons examiner l'expression rationnelle et la substitution. Si les premières correspondances alternatives (c'est-à-dire que nous avons fait correspondre n'importe quel caractère dans l'une des lignes), le (?<=(.*))
capture tout dans ce groupe jusqu'à ce caractère sur cette ligne 1
. Le $.1
dans le modèle de substitution le remplace par la longueur du groupe 1
. Par conséquent, le premier caractère de chaque chaîne devient 1
, le second devient 2
, le troisième devient3
et ainsi de suite. Il devrait être clair maintenant comment cela transpose une entrée carrée: tous les premiers caractères des lignes viennent en premier et se retrouvent tous dans la ligne la plus haute, puis tous les seconds caractères se retrouvent dans la deuxième ligne et ainsi de suite. Mais pour ces entrées rectangulaires, nous faisons également correspondre les sauts de ligne. Depuis le groupe1
n'est pas utilisé dans ce cas, la substitution est vide, mais aux fins de l' #
option, cela est considéré 0
. Cela signifie que tous les sauts de ligne sont triés vers l'avant.
Alors maintenant, nous avons les caractères dans le premier ordre (premier caractère de chaque chaîne, deuxième caractère de chaque chaîne, etc.) et tous les sauts de ligne au début.
Étape 2: Match
!`(?<=(¶)+.*)(?<-1>.)+
Nous devons maintenant diviser les caractères en lignes de la bonne longueur. Cette longueur correspond au nombre de lignes dans l'entrée d'origine, qui correspond au nombre de sauts de ligne que nous avons au début de la chaîne.
Le fractionnement se fait ici à l'aide d'une étape de correspondance, qui trouve simplement toutes les correspondances de l'expression régulière donnée et utilise l' !
option pour imprimer ces correspondances (la valeur par défaut serait de les compter à la place). Le but de l'expression régulière est donc de faire correspondre une ligne à la fois.
Nous commençons par «compter» le nombre avec le lookbehind (?<=(¶)*.*)
. Il génère une capture en groupe 1
pour chaque saut de ligne à l'avant.
Ensuite, pour chacune de ces captures, nous associons un seul caractère avec (?<-1>.)+
.