2

The basis of my problem is I am making a 14x14 crossword puzzle, I have the data for each of the 196 cells from an outside document, but need only the cells with text inside to have borders.

I tried using MetaPost to solve this. For simplicity, I've reduced the code to just a 14x1 grid example here.

I created an outside script which gives me all of the values that should go inside the grid. E.g., if the first row has "cat" across, then it gives this:

\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}

The full 14x14 example has 196 such variables, but place in another file by a script, so they aren't unwieldy.

I used MetaPost to create many boxes, rather than tables, as I could find no clean way to add the subscript text to the corner of a cell in a table without it pushing the letter in that cell to the right.

Here is the minimal working example of the solution page is this:

\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}

\define\crosswordsolution{%
    \scale[width=\textwidth]{%
        \startMPcode
            draw (0,0)--(100,0)--(100,100)--(0,100)--(0,0);
            draw (100,0)--(200,0)--(200,100)--(100,100)--(100,0);
            draw (200,0)--(300,0)--(300,100)--(200,100)--(200,0);
            draw (300,0)--(400,0)--(400,100)--(300,100)--(300,0);
            draw (400,0)--(500,0)--(500,100)--(400,100)--(400,0);
            draw (500,0)--(600,0)--(600,100)--(500,100)--(500,0);
            draw (600,0)--(700,0)--(700,100)--(600,100)--(600,0);
            draw (700,0)--(800,0)--(800,100)--(700,100)--(700,0);
            draw (800,0)--(900,0)--(900,100)--(800,100)--(800,0);
            draw (900,0)--(1000,0)--(1000,100)--(900,100)--(900,0);
            draw (1000,0)--(1100,0)--(1100,100)--(1000,100)--(1000,0);
            draw (1100,0)--(1200,0)--(1200,100)--(1100,100)--(1100,0);
            draw (1200,0)--(1300,0)--(1300,100)--(1200,100)--(1200,0);
            draw (1300,0)--(1400,0)--(1400,100)--(1300,100)--(1300,0);

            label("\getvalue{1}", (50,50));
            label("\getvalue{2}", (150,50));
            label("\getvalue{3}", (250,50));
            label("\getvalue{4}", (350,50));
            label("\getvalue{5}", (450,50));
            label("\getvalue{6}", (550,50));
            label("\getvalue{7}", (650,50));
            label("\getvalue{8}", (750,50));
            label("\getvalue{9}", (850,50));
            label("\getvalue{10}", (950,50));
            label("\getvalue{11}", (1050,50));
            label("\getvalue{12}", (1150,50));
            label("\getvalue{13}", (1250,50));
            label("\getvalue{14}", (1350,50));
            label("1", (25,75));
        \stopMPcode
    }%
}%

\starttext
    \crosswordsolution
\stoptext

The problem I have is that I need only those boxes with a letter inside to be drawn. The empty boxes needn't be drawn at all. In other words, only the boxes containing the letters in C-A-T need to be drawn, the others are invisible.

I tried using simple TeX conditionals inside MetaPost, checking if the variable is empty, but the code came up with errors, so I suspect MetaPost can't have TeX or ConTeXt code inside \startMPcode and \endMPcode.

Is there some way to create conditions that allows specific boxes to be drawn only if the matching variable has text?

6
+200

You will find it easier to use Metapost logical structures. Here is some plain MP, that does what (I think) you want:

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

    string cell[];
    cell1 := "C";
    cell2 := "A";
    cell3 := "T";
    cell4 := "";
    cell5 := "S";
    cell6 := "A";
    cell7 := "T";
    cell8 := "";
    cell9 := "";
    cell10 := "";
    cell11 := "H";
    cell12 := "E";
    cell13 := "R";
    cell14 := "E";

    path box;
    box = unitsquare shifted -(1/2, 1/2) scaled 10;

    numeric x, y;
    y = 5;
    x = 5;
    for i=1 upto 14:
        if cell[i] <> "": 
            label(cell[i], (x, y));
            draw box shifted (x, y);
        fi
        x := x + 10; 
    endfor

endfig;
end.

If you compile this with plain mpost you should get this:

enter image description here

Everything that works in plain Metapost between beginfig and endfig should work without change between \startMPcode and \stopMPcode in Context.

You could adapt this to your values by assigning cell1 := "\getvalue{1}" etc.

3

You can use TeX conditionals in MetaPost but they have to be fully-expandable and avoid the “incomplete if” problem. The resulting code is not pretty and Toby's answer is clearly preferable.

\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}

% \getvalue only yields its value after two expansion steps,
% therefore we need to use \doubleexpandafter
\def\expdoifvalue#1%
    {\doubleexpandafter\ifx\getvalue{#1}\empty
         \expandafter\gobbleoneargument
     \else
         \expandafter\firstofoneargument
     \fi}

\define\crosswordsolution{%
    \scale[width=\textwidth]{%
        \startMPcode
            \expdoifvalue{1}{
                draw (0,0)--(100,0)--(100,100)--(0,100)--(0,0);
                label("\getvalue{1}", (50,50));
            }
            \expdoifvalue{2}{
                draw (100,0)--(200,0)--(200,100)--(100,100)--(100,0);
                label("\getvalue{2}", (150,50));
            }
            \expdoifvalue{3}{
                draw (200,0)--(300,0)--(300,100)--(200,100)--(200,0);
                label("\getvalue{3}", (250,50));
            }
            \expdoifvalue{4}{
                draw (300,0)--(400,0)--(400,100)--(300,100)--(300,0);
                label("\getvalue{4}", (350,50));
            }
            \expdoifvalue{5}{
                draw (400,0)--(500,0)--(500,100)--(400,100)--(400,0);
                label("\getvalue{5}", (450,50));
            }
            \expdoifvalue{6}{
                draw (500,0)--(600,0)--(600,100)--(500,100)--(500,0);
                label("\getvalue{6}", (550,50));
            }
            \expdoifvalue{7}{
                draw (600,0)--(700,0)--(700,100)--(600,100)--(600,0);
                label("\getvalue{7}", (650,50));
            }
            \expdoifvalue{8}{
                draw (700,0)--(800,0)--(800,100)--(700,100)--(700,0);
                label("\getvalue{8}", (750,50));
            }
            \expdoifvalue{9}{
                draw (800,0)--(900,0)--(900,100)--(800,100)--(800,0);
                label("\getvalue{9}", (850,50));
            }
            \expdoifvalue{10}{
                draw (900,0)--(1000,0)--(1000,100)--(900,100)--(900,0);
                label("\getvalue{10}", (950,50));
            }
            \expdoifvalue{11}{
                draw (1000,0)--(1100,0)--(1100,100)--(1000,100)--(1000,0);
                label("\getvalue{11}", (1050,50));
            }
            \expdoifvalue{12}{
                draw (1100,0)--(1200,0)--(1200,100)--(1100,100)--(1100,0);
                label("\getvalue{12}", (1150,50));
            }
            \expdoifvalue{13}{
                draw (1200,0)--(1300,0)--(1300,100)--(1200,100)--(1200,0);
                label("\getvalue{13}", (1250,50));
            }
            \expdoifvalue{14}{
                draw (1300,0)--(1400,0)--(1400,100)--(1300,100)--(1300,0);
                label("\getvalue{14}", (1350,50));
            }

            label("1", (25,75));
        \stopMPcode
    }%
}%

\starttext
    \crosswordsolution
\stoptext

Instead of implementing \expdoifvalue{1}{...} you could also use the builtin \expdoifnot{\getvalue{1}}{}{...}. However, \expdoifnot performs a full expansion which might not always be desirable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.