2

I am playing with LuaLaTeX substitutions, trying to find a way to replace a string within a macro with random characters of the same length.

The chickenize package offers the randomchars function which does this for an entire paragraph. However, I cannot get this to work on just the argument of the TeX macro, and get either errors or nothing when trying to create a macro like:

\newcommand{\rndm}[1]{\directlua{randomchars(#1)}}

  • Do uppercase and lowercase have to be respected? Or should it be all uppercase, all lowercase, or should the case status of letters be random as well (presumably 50-50, right)? Should whitespace be preserved as such? What about any digits in the string: Should they be replaced with other, randomly chosen digits? Please advise. – Mico Jan 30 '22 at 13:52
  • 1
    Any character in unicode is fine, but whitespace should be respected (so abcd can be replaced with !RX? ) – luaplaying Jan 30 '22 at 13:56
  • Imho, this is a better question for a Lua community, where you'd most likely get the broader audience. Afterwards it's just tex.print the results. – Skillmon Jan 30 '22 at 14:43
  • Perhaps something along these lines: https://tex.stackexchange.com/questions/450795/latex-uglifier-obfuscator. Also, "of same length" I presume you mean same number of characters, and not same textual width? – Steven B. Segletes Jan 30 '22 at 17:00
  • I should note my above comment is an alternative to lua. – Steven B. Segletes Jan 30 '22 at 18:00
  • @Skillmon -- I think there is a TeX-specific "angle" in this query, as one has to be careful about how to go outputting TeX-special characters such as & and $. – Mico Jan 30 '22 at 21:22

1 Answers1

2

Here you go. Note that the input and output characters could be (almost) arbitrary utf8-encoded characters. (On output, it's your job to verify that the output characters are indeed present in the font that's in use.) If the characters are TeX-special -- say, & and $ -- be sure to escape them as \\& and \\$, etc. Whitespace in the input string is preserved, but punctuation characters aren't given any preferential treatment.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for 'luacode' environment and '\luastring' macro
\begin{luacode}
function rndstring ( inputstring )
  local outputstring, choices, mm, nn
  mm = unicode.utf8.len(inputstring) -- no. of utf8-encoded characters in input string

-- Place candidate replacement characters in a Lua table: choices = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "\#", "\$", "\%", "\%", "\&", "\_", "\textbackslash{}", "*", "+", "-", "/", "(", ")", "[", "]", "\{", "\}", "<", "=", ">", "?", "@", "\textasciitilde{}", "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", "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" } -- Number of rows in 'choices' table nn = #choices

-- Generate the outputstring in a 'for' loop: outputstring = "" for i = 1 , mm do if unicode.utf8.sub ( inputstring , i , i ) == " " then outputstring = outputstring .. " " -- preserve space char. else -- choose a new char randomly from 'choices' table outputstring = outputstring .. choices[ math.random ( nn ) ] end end

return ( outputstring ) end

\end{luacode}

%% Define a LaTeX macro to invoke the Lua function
\newcommand\rndstring[1]{\directlua{tex.sprint(rndstring(\luastring{#1}))}}

%% test strings to feed to '\rndstring':
\newcommand\stringA{Hello World}
\newcommand\stringB{Hello Владимир öäüß}
\newcommand\stringC{Once upon a time, there was ...}

\begin{document}
\ttfamily % optional

\rndstring{\stringA}\par\rndstring{\stringB}\par\rndstring{\stringC}

\bigskip
\rndstring{\stringA}\par\rndstring{\stringB}\par\rndstring{\stringC}

\end{document}
Mico
  • 506,678
  • Why not use #choices to get the number of choices in the table? – Skillmon Jan 30 '22 at 23:33
  • @Skillmon - Good question! :-) I guess it's because of an old (aquired) habit of mine: In general, one should not assume that the two methods provide the same result. However, after about 10 seconds of thought, it's clear to me too that for the Lua table at hand, the two methods must provide the same result, since there are no "gaps" in this table. Indeed, I rely on this result implicitly later on, when I select a table entry randomly via choices[ math.random ( nn ) ]. I'll go ahead and fix this issue in the code. – Mico Jan 31 '22 at 00:34
  • 1
    I knew about the peculiarities of table access in Lua with the # operator (just came to the same conclusion as you here, in that it is the same if the table assignment is done this way). – Skillmon Jan 31 '22 at 06:13
  • 1
    magnificent, thank you! – luaplaying Jan 31 '22 at 16:49