37

Here's a fun challenge. Try to come up with (and code) techniques through which (La)TeX can help authors to incorporate acrostics in their writing. The definition from Wikipedia:

An acrostic is a poem or other form of writing in which the first letter, syllable or word of each line, paragraph or other recurring feature in the text spells out a word or a message.

The article contains a number of interesting examples.

I don't expect TeX to do all the work (although that would earn you big bonus points), but I can imagine a number of ways in which it might assist:

  1. Allow the author to assert that a specific acrostic is present and generate a warning/error if it isn't.
  2. For the "first of every line" variety, subtly adjust line-breaking points to help.
  3. Optionally display the parts of the secret message that already 'line up' with different formatting.

If you have other good ideas or, better yet, working code (doesn't have to be perfect), do share it with the rest of us! :-)

Clarification of the Idea

My initial purpose in posing this challenge was to collaboratively write a package that allows you, first and foremost, to embed hidden messages into a text. I agree that the question as posed was misleading.

Ideally, the casual reader should not become aware that there was an acrostic present at all, so linebreaks should follow from the natural flow of text.

That is the challenge for the author. The package I had in mind would allow the author to state what message he wants to hide and where. The interface could look something like this (using Davids example):

\begin{acrostic}{1 letter}{every line}{TeXisfun}
    The trick is to let the system find the line breaks such
    that the expected letter starts each line. It is much easier
    if the source is XML. This main text is more or less relevant
    to the subject raised in the question. This text is far more
    interesting than boring Lipsum that you see in so many other
    answers on this site. You may find a distinct lack of TikZ in
    this answer, booktabs doesn't show up and nor does Lua. You
    will note how no special markup is needed: \TeX\ has a built-
    in ability to find the correct breaks.
\end{acrostic}

As mentioned above, LaTeX might then:

  • Warn the author when his acrostic is broken and,
  • to some degree, force the acrostic to appear by subtle manipulation of line-breaking penalties, or by some other clever tactic.

That is the ideal scenario, and may be infeasible. I imagine it is easier to implement other solutions that are "almost as good", such as allowing the author to explicitly mark the relevant letters inside the full text, and letting LaTeX work off that.

Collected Ideas from Comments and Answers

  1. For the "first of every line" variety: subtly adjust \textwidth to help. [by David Carlisle]
  2. For the "first of every line" variety: rather than maintain the natural flow of text and warn the author when the acrostic is broken, we can do the opposite and force the acrostic flush against the left margin and warn the author when the paragraph is too loose or tight. [by Steven B. Segletes]
  3. We'll need special treatment for acrostics spanning multiple sections or chapters. [by Ivan Andrus]
3
  • I did this with the first letter of each chapter of my dissertation. It was quite fun. If there had been a package to help I might have tried a longer message than just 5 letters. Jul 3, 2013 at 2:05
  • With the titles? :-) Anyway, yet another good thought. Something that spans multiple sections/chapters can't possibly be 'contained' by one macro or environment, so some standard document commands might need to be redefined in order for TeX to keep track.
    – mhelvens
    Jul 3, 2013 at 10:34
  • Addendum added to my solution to bring real-world practical application to the use of acrostics. Jul 7, 2013 at 3:20

2 Answers 2

34

NOTE: Real-world application added at end of post! RE-REVISED to re-extend capability (and significantly condense the coding), as detailed here:

The following macros are introduced for left-aligned acrostics. Macros for mid-line acrostics are described later in this post.

\RAWacrostic{acrostic} - to view acrostic in plain, unaltered mode

\SHOWacrostic[# acrostic chars]{acrostic} - to view with acrostic highlighted (cap bold), unflushed.

\MEASUREacrostic[test width]{acrostic} - to view natural widths of each line of the acrostic. With an optional length argument, it will tell you the interword spacing that will result from flushing the acrostic into the given length. Note: the width must be provided as a string, as in 200pt or \the\textwidth.

\FLUSHacrostic[width]{acrostic} - to flush the acrostic into a paragraph. The width will be \textwidth unless otherwise specified by the optional argument.

The macro \SHOWacrostic takes an optional argument of how many of the initial characters to capitalize and make bold. The helper macro \accnt is what capitalizes and makes those characters bold. \accnt also looks to avoid highlighting initial punctuation, instead looking for letters. To see this feature, look in the output for the line containing ```Love not''` where the "L" and not the quotes are emboldened.

\MEASUREacrostic may give guidance as to how to improve the lengths as well as what width to set the text in. \FLUSHacrostic takes, as an optional argument, the width to set the text in. Of course, if you have large discrepancy of length in the lines of your acrostic, then it won't look so good.

Mid-line acrostics are also introduced [see more mentioned at end of this post].

EDITED to restore functionality lost to ravages of package upgrade.

\documentclass{article}
\usepackage{stackengine, stringstrings, calc}
\parskip 1em
\newcounter{index}
\def\stackalignment{l}
\def\stacktype{L}
\newcounter{nexttolast}
\newcounter{wordindex}
\newcounter{linegaps}
\newlength\natwidth
\newlength\extragapwidth
\newlength\spacewidth
\newsavebox{\verseline}
\sbox{\verseline}{-}
\setlength\spacewidth{\wd\verseline}
\makeatletter

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The \getargsC macro mimics the behavior of the \getargs macro
% of the stringstrings package, but runs faster, and can handle
% arbitrary tokens.  For the development of \getargsC, significant
% assistance was provided by David Carlisle, for which the author is
% most appreciative.
% http://tex.stackexchange.com/questions/101604/
%      parsing-strings-containing-diacritical-marks-macros
%
\def\string@end{$\SaveHardspace}
\def\converttilde{F}
\newcounter{arg@index}
\newcounter{break@count}
\let\SaveHardspace~%%%
%
\def\getargsC#1{%
  \if T\converttilde\def~{ }\else\catcode`~=12\fi
  \protected@edef\the@string{#1}%
  \setcounter{arg@index}{0}%
  \lowercase{\expandafter\parse@Block\the@string} \string@end
  \let~\SaveHardspace%
  \catcode`~=13
}
%
\def\parse@Block#1 {%
  \stepcounter{arg@index}%
  \@namedef{arg\roman{arg@index}}{#1}%
  \futurelet\tmp\parse@Block@}
%
\def\parse@Block@{%
\ifx\tmp\string@end\edef\narg{\thearg@index}\expandafter\@gobble
\else\expandafter\parse@Block\fi}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand\@acrostic[3]{%
  \def\quietstack{T}%
  \getargsC{#2}%
  \setcounter{nexttolast}{\narg}%
  \addtocounter{nexttolast}{-1}%
  \setcounter{index}{1}%
  \if R#3\sbox{\stackedbox}{\argi}\else%
  \if S#3\sbox{\stackedbox}{\@accnt{\argi}{#1}}\else%
  \if M#3\if x#1\else(Ref: #1)\fi\sbox{\stackedbox}{\@measure{\argi}{#1}}\else%
  \if F#3\sbox{\stackedbox}{\@fittowidth{\argi}{#1}}%
  \fi\fi\fi\fi%
  \whiledo{\value{index}<\value{nexttolast}}{%
    \stepcounter{index}%
    \edef\poemline{\csname arg\roman{index}\endcsname}%
    \if R#3\stackon{\poemline}{\usebox{\stackedbox}}\else%
    \if S#3\stackon{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}\else%
    \if M#3\stackon{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}\else%
    \if F#3\stackon{\@fittowidth{\poemline}{#1}}{\usebox{\stackedbox}}%
    \fi\fi\fi\fi%
  }%
  \stepcounter{index}%
  \edef\poemline{\csname arg\roman{index}\endcsname}%
  \if R#3\stackon{\poemline}{\usebox{\stackedbox}}\else%
  \if S#3\stackon{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}\else%
  \if M#3\stackon{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}\else%
  \if F#3\stackon{\poemline}{\usebox{\stackedbox}}%
  \fi\fi\fi\fi%
  \usebox{\stackedbox}%
  \def\quietstack{F}%
}
\newcommand\RAWacrostic[2][1]{\@acrostic{#1}{#2}{R}}
\newcommand\SHOWacrostic[2][1]{\@acrostic{#1}{#2}{S}}
\newcommand\MEASUREacrostic[2][x]{\@acrostic{#1}{#2}{M}}
\newcommand\FLUSHacrostic[2][\textwidth]{\@acrostic{#1}{#2}{F}}

\newcommand\@MIDacrostic[3]{%
  \getargsC{#2}%
  \setcounter{nexttolast}{\narg}%
  \addtocounter{nexttolast}{-1}%
  \setcounter{index}{1}%
  \if R#3\sbox{\stackedbox}{\argi}\else%
  \if S#3\sbox{\stackedbox}{\argi}\else%
  \if M#3\if x#1\else(Ref: #1)\fi\sbox{\stackedbox}{\@measure{\argi}{#1}+}%
  \fi\fi\fi%
  \whiledo{\value{index}<\value{nexttolast}}{%
    \addtocounter{index}{2}%
    \edef\poemline{\csname arg\roman{index}\endcsname}%
    \if R#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}\else%
    \if S#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}\else%
    \if M#3\stackengine{\Lstackgap}{\@measure{\poemline}{#1}+}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}%
    \fi\fi\fi%
  }%
  \usebox{\stackedbox}%
\if R#3#1\fi%
  \setcounter{index}{2}%
  \if R#3\sbox{\stackedbox}{\argii}\else%
  \if S#3\sbox{\stackedbox}{\@accnt{\argii}{#1}}\else%
  \if M#3\sbox{\stackedbox}{\@measure{\argii}{#1}}%
  \fi\fi\fi%
  \whiledo{\value{index}<\narg}{%
    \addtocounter{index}{2}%
    \edef\poemline{\csname arg\roman{index}\endcsname}%
    \if R#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}\else%
    \if S#3\stackengine{\Lstackgap}{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}\else%
    \if M#3\stackengine{\Lstackgap}{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}%
    \fi\fi\fi%
  }%
  \usebox{\stackedbox}%
}
\newcommand\RAWMIDacrostic[2][]{\@MIDacrostic{#1}{#2}{R}}
\newcommand\SHOWMIDacrostic[2][1]{\@MIDacrostic{#1}{#2}{S}}
\newcommand\MEASUREMIDacrostic[2][\textwidth]{\@MIDacrostic{x}{#2}{M}}
% HELPER ROUTINES
\newcommand\@fittowidth[2]{%
  \getargsC{#1}%
  \setcounter{wordindex}{1}%
  \parbox[b]{#2}{%
    \argi%
    \whiledo{\value{wordindex} < \narg}{%
      \stepcounter{wordindex}%
      \hfill\csname arg\roman{wordindex}\endcsname%
    }%
  }%
}
\newcommand\@measure[2]{%
  \sbox{\verseline}{#1}%
  \setlength\natwidth{\wd\verseline}%
  \the\natwidth%
  \if x#2\else%
  \getargsC{#1}%
  \setcounter{linegaps}{\narg}%
  \addtocounter{linegaps}{-1}%
  \setlength\extragapwidth{(#2-\natwidth)/\thelinegaps+\spacewidth}%
  (\the\extragapwidth)%
  \fi%
}
\newcommand\@accnt[2]{%
  \if T\ignorepunctuation%
    \alphabetic[q]{#1}%
    \substring[q]{\thestring}{1}{1}%
    \edef\searchletter{\thestring}%
    \whereischar[q]{#1}{\searchletter}%
    \edef\searchletterloc{\theresult}%
  \else%
    \edef\searchletterloc{1}%
  \fi%
          \substring{#1}{1}{\searchletterloc-1}%
          \substring[q]{#1}{\searchletterloc}{\searchletterloc+#2-1}%
          \textbf{\caseupper{\thestring}}%
          \substring{#1}{\searchletterloc+#2}{$}%
}
\def\ignorepunctuation{T}
\makeatother
\parindent 0in
\begin{document}
\SHOWacrostic{My very excellent mother just served us nachos}
tells us the planets: 
\SHOWacrostic{Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune}

\def\months{%
 {Janet was quite ill one day.}
 {Febrile trouble came her way.}
 {Martyr-like, she lay in bed;}
 {Aproned nurses softly sped.}
 {Maybe, said the leech judicial}
 {Junket would be beneficial.}
 {Juleps, too, though freely tried,}
 {Augured ill, for Janet died.}
 {Sepulchre was sadly made.}
 {Octaves pealed and prayers were said.}
 {Novices with ma'y a tear}
 {Decorated Janet's bier.}}

\RAWacrostic[3]{\months}
~~
\SHOWacrostic[3]{\months}

\clearpage
\def\liz{%
 {Elizabeth it is in vain you say}
 {``love not'' thou sayest it in so sweet a way:}
 {in vain those words from thee or L.E.L.}
 {Zantippe's talents had enforced so well:}
 {Ah! if that language from thy heart arise,}
 {breath it less gently forth and veil thine eyes.}
 {Endymion, recollect, when Luna tried}
 {to cure his love was cured of all beside}
 {his follie pride and passion for he died.}}
%
\RAWacrostic{\liz}

\SHOWacrostic{\liz}

\MEASUREacrostic{\liz}~~~~~
\MEASUREacrostic[185pt]{\liz}


The measuring algorithm assumes a natural space is the same width as a
hyphen, namely \the\spacewidth.

\FLUSHacrostic[185pt]{\liz}  $\leftarrow$ verse set to 185pt width
\clearpage

\def\midway{%
  {The programming } {language I am}
  {trying to imagine } {at the moment,}
  {I am told, is qui} {te fun to use,}
  {as David Carlisl} {e spoke of in}
  {a very a proli} {x manner.}}

\RAWMIDacrostic[\hspace{.1ex}\rule{.4ex}{4.7\baselineskip}\hspace{.1ex}]
  {\midway}

\RAWMIDacrostic{\midway}

Measure:
\MEASUREMIDacrostic{\midway}

\SHOWMIDacrostic{\midway}

\def\ignorepunctuation{F}

\def\ode{%
{You~~~~} {\ \ \ \ are a}
{truly amaz} {ing woman:}
{with grace, } {laughter, fun.}
{And then y} {ou are seen}
{showing lo} {ve always.}
{I most } {especially}
{know } {you're}
{a h} {oney}
{b} {un} {} {!!}}

\RAWMIDacrostic{\ode}~~~~~
\SHOWMIDacrostic{\ode}

\end{document}

In this first image, I demonstrate how \SHOWacrostic can be used with 1 or more letters in the acrostic (passed as an optional argument). Note how \SHOWacrostic will capitalize and embolden the acrostic, as compared to the raw acrostic shown on the left.

enter image description here

In this image, I demonstrate more power for left-aligned acrostics. I first show the raw acrostic as entered with \RAWacrostic. Then I show it revealed with \SHOWacrostic. Then I measure it in two ways with \MEASUREacrostic. If no optional argument is provided, it shows the natural length of each line. If a length string (use \the if providing a macro) is provided as the optional argument, it shows the measurements, as before, but adds in parentheses the calculated interword spacing for each line, if the acrostic were to be flushed to the given width. These can be used to quantitatively gauge whether the gaps are too big or small. Finally, I set the acrostic to that flushed width with \FLUSHacrostic.

enter image description here

Additionally,

\RAWMIDacrostic[divider]{acrostic}

\MEASUREMIDacrostic{acrostic} and

\SHOWMIDacrostic[# acrostic chars]{acrostic}

have been added for mid-line acrostics. First, I show the acrostic with a rule dividing the two halves. This is the reason the acrostic itself must have left and not center alignment, because the acrostic is formed by butting the two (already stacked) halves together. Then I show the raw acrostic verse, with the message hidden. I then show the measurements of both halves of each line. Note, that since I don't (yet) provide flushing for mid-acrostics, I do not provide the means to compare these lengths to two test-widths. Lastly, I reveal the acrostic with \SHOWMIDacrostic.

enter image description here

Making mid-acrostics flush to margins is an exercise left to the reader. ;^)

However, guys, here's where you need to take some close notes. Even without flushing for mid-line acrostics, you can make highly profitable use of the mid-acrostics. Think of your best girl, and compose her a verse, sure to melt her heart. I promise you, good things will follow.

enter image description here

9
  • Looks like a good next step! This kind of highlighting is a useful feature for acrostics writers. --- I think I was unclear in my original problem statement, however. To clarify (and I'll edit the question too), I want to embed 'hidden' messages into a text by way of acrostics. Linebreaks should follow the natural flow of the text, and the casual reader should not realize there was any acrostic there at all. --- Highlighting, in that scenario, is more of a debugging tool.
    – mhelvens
    Jul 1, 2013 at 15:04
  • @mhelvens Okay, I was just going based on the reference page you cited. So what is the goal? for the writer to have the hidden text in mind, and LaTeX will auto-build a paragraph to produce it? Will the acrostic message always be left-most column or "anywhere", as in the style of those find-the-word games with a matrix of seemingly random letters? Jul 1, 2013 at 15:19
  • I've updated the question. And yeah, the Wikipedia article I cited is totally misleading. My bad. --- As for the location of the acrostic, I've left that part open. It could be the first two letters of every line, the last word of every other paragraph or, more generally, the [ordinal] [number] [textual unit] of every [ordinal] [larger textual unit]. I imagine the "first letter of every line" variety is most interesting.
    – mhelvens
    Jul 1, 2013 at 15:32
  • Just noticed your edits (coincidentally; edits don't generate notifications). --- Cool! Whereas my initial idea was to keep the text flowing normally, possibly warning you if the acrostic breaks, in your approach the acrostic never breaks, but you might get ugly spacing. Two (presumably easy) ways to improve your code: [1] Warn the author when the inter-word glue is stretched or compressed beyond established limits. [2] Mid-acrostic letters are still 'aligned left'. Might be nicer to center them. --- Cheers!
    – mhelvens
    Jul 2, 2013 at 19:54
  • @mhelvens As far as suggestion 2, it is not possible with my approach, as I basically abut two stacks of text. If I instead created a third stack with center-aligned acrostic letters (of unequal width), it would (following abutment) screw up the spacing to the adjacent letters. As to suggestion #1, the purpose of \MEASURE... was to give the user a feel for how much glue is being used. If I can think of a better way, I'll consider adding it. Jul 2, 2013 at 20:01
18
\hsize10.25cm
\raggedright
\parindent0pt


The trick is to let the system find the line breaks such that the expected letter starts each line.
It is much easier if the source is XML. This main text is more or less relevant to the subject
raised in the question. This text is far more interesting than boring Lipsum that you see in
so many other answers on this site. You may find a distinct lack of TikZ in this answer,
booktabs doesn't show up and nor does Lua. You will note how no special markup is needed:
\TeX\ has a built-in ability to find the correct breaks.


\bye
10
  • Woah, that's pretty neat!
    – Jake
    Jun 27, 2013 at 20:00
  • 1
    A good start! How long did it take you to write this? --- Imagine how tricky it might be for a longer message, without the freedom to choose an arbitrary \hsize. That's why some 'intelligent' assistance from TeX might be very cool. --- Still, changing \hsize is a useful tool for this, and I hadn't yet considered it. If the change is subtle enough (and restricted to the relevant pages), the reader might never notice. --- A next step might be: allow the author to mark each letter of the message and let TeX find the proper \hsize automatically.
    – mhelvens
    Jun 27, 2013 at 20:08
  • 1
    @mhelvens Not sure when I saw your question, less than 28 minutes according to the timestamps, probably 15 or so:-) Jun 27, 2013 at 20:29
  • 5
    @mhelvens: Don't forget that David wrote xii.tex.
    – Aditya
    Jun 27, 2013 at 23:43
  • 3
    Just in case someone is wondering what the output looks like: i.stack.imgur.com/qDVko.png :) Jul 3, 2013 at 8:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .