# Reading an input word in an array and then processing character by character

For some application, I need to read input tex file word by word (not necessarily as arguments of any command), and then to print each word after changing the positions of some characters within the word based on some conditions. For example, the word 'eat' may need to be printed as 'ate' or 'tea'. Is any such provision available in LaTeX?

• it would be possible but likely to be much easier in perl or python or Lua or .. depending on the nature of the "some conditions" – David Carlisle May 6 at 13:14

This code defines a macro \InputSwap which reads a file, splits the input at the spaces to make up words, and then processes each word based on \dilip_some_conditions:nnTF.

The conditional function \dilip_some_conditions:nnTF takes two letters and returns them either in their original order or swapped. The only formal verification is done with punctuation. Should any of the characters in \c__dilip_punct_tl (.,'/?;:!()[] by default; add more at will) appear in the pair of characters being tested, they are returned in the same order, otherwise they are randomly swapped. Depending on what conditions you should wish to fulfill you'll have to modify the \dilip_some_conditions:nnTF function.

Depending on how you want to swap the letter you'd need a different code, perhaps without the \tl_sort:nN thing at all.

Using a paragraph of Lorem ipsum as input, the result is:

Here's the code:

\RequirePackage{filecontents}
\begin{filecontents*}{\jobname.words}
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
\end{filecontents*}
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__dilip_input_tl
\NewDocumentCommand \InputSwap { O { \dilip_some_conditions:nnTF } m }
{ \dilip_input_swap:Nn #1 {#2} }
\cs_new_protected:Npn \dilip_input_swap:Nn #1 #2
{
\file_get:nnNTF {#2} {} \l__dilip_input_tl
{ \exp_args:NNV \__dilip_iterate_input:Nn #1 \l__dilip_input_tl }
{ \__kernel_msg_error:nnn { kernel } { file-not-found } {#2} }
}
\cs_set:Npn \__dilip_tmp:w #1
{
\cs_new_protected:Npn \__dilip_iterate_input:Nn ##1 ##2
{ \__dilip_iterate_input:Nw ##1 ##2 #1 \q_recursion_tail #1 \q_recursion_stop }
\cs_new_protected:Npn \__dilip_iterate_input:Nw ##1 ##2 #1
{ \tl_trim_spaces_apply:nN {##2} \__dilip_process_word:nN ##1 }
}
\__dilip_tmp:w { ~ }
\cs_new_protected:Npn \__dilip_process_word:nN #1 #2
{
\quark_if_recursion_tail_stop:n {#1}
\tl_sort:nN {#1} \dilip_some_conditions:nnTF
\__dilip_continue:N #2
}
\prg_new_conditional:Npnn \dilip_some_conditions:nn #1 #2 { TF }
{
\tl_if_in:NnTF \c__dilip_punct_tl {#1}
{ \prg_return_true: }
{
\tl_if_in:NnTF \c__dilip_punct_tl {#2}
{ \prg_return_true: }
{
\int_compare:nNnTF { \int_rand:nn {1} {2} } > { 1 }
{ \prg_return_true: }
{ \prg_return_false: }
}
}
}
\tl_const:Nn \c__dilip_punct_tl { .,'/?;:!()[] }
\cs_new_protected:Npn \__dilip_continue:N #1 { \__dilip_iterate_input:Nw #1 }
\ExplSyntaxOff
\begin{document}
\InputSwap{\jobname.words}
\end{document}

• My requirement is different. Actually I want to process a non-English mixed file. For example, please see the following illustrative code. Say, the texts with {\it } declaration does not require any change, but those with {\bf } declaration only. Here I need to put intermediate/ending 'e', 'i' and 'ui' prior to the immediate preceding consonant(s). That is, the statement in {\bf } should be printed as `iThs non-Einglsh ilen eruiqers swaippng'. Can you please help me on it? – Dilip D. May 6 at 18:23
• \documentclass{article} \begin{document} {\it It is a statement in English.} \par {\bf This non-English line requires swapping.} \end{document} – Dilip D. May 6 at 18:24
• @DilipD. Well, it's a quite different problem, actually, and the solution I proposed won't be of any use. It's what happens when you ask a “XY question”. I suggest you mark this question as solved and ask a new question with the specifications you gave in the comment above. I say that because (a) It would sort of invalidate the Question/Answer model of this site, with an answer that (solves your problem but) doesn't match the original question (b) more people will see your question and you have much better chances of getting a good answer. – Phelype Oleinik May 6 at 18:45