2

In my previous question, How to set macro for looping with minipage?, I was suggested using a foreach loop to solve the problem. After testing, the loop works correctly as show in page 1 pdf. However, when more FENs are added, loop gives wrong format as shown in pdf 2 and 3. Any suggestion on how to fix the foreach loop is appreciated.

\documentclass{article}
\usepackage{xskak,chessboard}
\usepackage[margin=3cm]{geometry}
\begin{document}

%**** WORKSHEET 1 IS CORRECT; WORKSHEET 2 AND 3 IS WRONG ******
%********************************************************
%******CORRECT WORKSHEET USING FOREACH LOOP *******

\foreach \X/\Y in 
{basic/{3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
%******* PAWN LEVEL *****************
pawn/{8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
%************ 2 PAWN LEVEL *******************
2 pawns/{8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
%************ MINOR + PAWN LEVEL ********************
Minor + Pawns/{4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
 8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1}}
{\noindent\tikz{\node[rotate=90,font=\bfseries,align=center,text width=4cm]{\X};}
\foreach \Z in \Y
{\begin{minipage}[b]{0.35\linewidth}
\chessboard[smallboard,setfen=\Z]
\end{minipage}}

}
%****** WHEN NEW FENS ARE ADDED, FOREACH LOOP GETS WRONG. WORKSHEET IS NOT SAME AS **
%**** PREVIOUS WORKSHEET *****
\foreach \X/\Y in 
{basic/{3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
basic/{3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
%******* PAWN LEVEL *****************
pawn/{8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
pawn/{8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
%************ 2 PAWN LEVEL *******************
2 pawns/{8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
2 pawns/{8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
%************ MINOR + PAWN LEVEL ********************
Minor + Pawns/{4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1},
Minor + Pawns/{4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1}}
{\noindent\tikz{\node[rotate=90,font=\bfseries,align=center,text width=4cm]{\X};}
\foreach \Z in \Y
{\begin{minipage}[b]{0.35\linewidth}
\chessboard[smallboard,setfen=\Z]
\end{minipage}}
\par
}
\end{document}
user92127
  • 187
  • The code runs through without an error on my TeXLive 2019 installation when compiled with pdflatex. Any chance you mean by error "undesired output"? If so, what would you like to have changed? –  Jun 22 '19 at 20:31
  • if you want to repeat the first page you should better store it in a box and reuse that box. That would be faster. But beside this: if you have lots of positions if would imho cleaner to store them first in some data structure, eg. an expl3-sequence and then to loop over this sequence. – Ulrike Fischer Jun 22 '19 at 20:43
  • @Marmot - your code works correctly. As stated, the ideal output is page 1. Your codes produce page 2 and 3 which is not like page 1. The sheet must pull data from each of the 4 group and lay them out like in page 1. – user92127 Jun 23 '19 at 00:09
  • @UlrikeFischer - I am trying to learn about expl3. Unfortunately, there's no "Expl3 for dummies" so I am stuck. I am looking for an example which I can test. I don't see examples done with chess before. Any suggestion is appreciated. – user92127 Jun 23 '19 at 00:12
  • Like marmot, I don't understand what the problem is with pages 2 and 3. Can you say more clearly what you mean by "page 2 and 3 which is not like page 1"? –  Jun 23 '19 at 00:23
  • @Andrew - run my code. In the output, there are three pages. Page 1 shows 4 groupings. Page 2 and 3 show overlapping of the group. – user92127 Jun 23 '19 at 00:31
  • I have, of course, already run your code. I don't see any overlapping groups. Are you, perhaps, asking about the repetition in the row order: basic, basic, pawns, pawns, ...? If so, this is the order that you have in the LaTeX code, so of course this is what you get. Please clearly explain what is wrong with the current output and what you want it to look like. I am sure that it is clear to you what you want but from what you have written, and perhaps I am being thick, it is not clear to me. –  Jun 23 '19 at 00:41
  • here's an image of my output:https://imgur.com/a/yBO1XlS – user92127 Jun 23 '19 at 00:44
  • As I said, I have run your code. I get the same output, so your image is of no help whatsoever. Please clearly explain what the problem is and what you are trying to achieve. –  Jun 23 '19 at 00:53
  • I don't where I miscommunicate. My output has three pages. 1st page clearly shows order of basic, pawn, 2pawn, and Minor+Pawn. That's what I want for page 2 and page 3. However, page 2 and 3 show different order. That's what the image shows. Don't you see the three pages are different. Can page 2 and 3 be the same as page 1. – user92127 Jun 23 '19 at 02:48

1 Answers1

3

Here is one solution using expl3:

\documentclass{article}
\usepackage{chessboard}
\usepackage{xskak}
\usepackage[margin=2cm]{geometry}
\usepackage{tikz}
\usepackage{xparse}

\ExplSyntaxOn

\msg_new:nnn { mychess } { groups-have-different-number-of-series }
  { all~groups~must~have~the~same~number~of~series~ (found~\exp_not:n {#1}~
    and~\exp_not:n {#2}). }

\seq_new:N \g_mychess_groups_seq

\cs_new_protected:Npn \mychess_define_groups:n #1
  {
    \seq_gset_from_clist:Nn \g_mychess_groups_seq {#1}
  }

% #1: group name (A, B, C, ...)
% #2: diagram data for this group (a comma list)
\cs_new_protected:Npn \mychess_set_group_diagrams:nn #1#2
  {
    \seq_gclear_new:c { g_mychess_group_#1_seq }
    \seq_gset_from_clist:cn { g_mychess_group_#1_seq } {#2}
  }

% Expand to the number of series declared for group #1
\cs_new:Npn \mychess_nb_series_for_group:n #1
  {
    \seq_count:c { g_mychess_group_#1_seq }
  }

\cs_generate_variant:Nn \mychess_nb_series_for_group:n { V }
\cs_generate_variant:Nn \msg_error:nnnn { nnVx }

\tl_new:N \l__mychess_a_group_tl
\int_new:N \l__mychess_nb_series_int

\cs_new_protected:Npn \mychess_print_all_diagrams:
  {
    % Get the name of the first group and the number of series declared for
    % this group (any other group would do, as they must have the same number
    % of series---which we are going to check right now as a safety measure
    % against invalid user input).
    \seq_get_left:NN \g_mychess_groups_seq \l__mychess_a_group_tl
    \int_set:Nn \l__mychess_nb_series_int
      { \mychess_nb_series_for_group:V \l__mychess_a_group_tl }

    % Check that the same number of series was defined for each group, and
    % print an error message if this is not the case.
    \seq_map_inline:Nn \g_mychess_groups_seq
      {
        \int_compare:nNnF
          { \mychess_nb_series_for_group:n {##1} }
          =
          { \l__mychess_nb_series_int }
          {
            \msg_error:nnVx { mychess }
              { groups-have-different-number-of-series }
              \l__mychess_nb_series_int
              { \mychess_nb_series_for_group:n {##1} }
          }
      }

    % Print all diagrams in series order, then in group order inside each
    % series.
    \int_step_function:nN { \l__mychess_nb_series_int }
      \mychess_print_diagrams_for_series:n
  }

\seq_new:N \l__mychess_print_one_diagram_set_tmp_seq

% #1: group name
% #2: data (a comma list: of rounds? Not sure about what the data represents)
\cs_new_protected:Npn \mychess_print_one_diagram_set:nn #1#2
  {
    \par \noindent
    \tikz { \node[rotate=90,font=\bfseries,align=center,text~width=4cm] {#1}; }
    \seq_set_from_clist:Nn \l__mychess_print_one_diagram_set_tmp_seq {#2}
    \seq_map_inline:Nn \l__mychess_print_one_diagram_set_tmp_seq
      {
        \chessboard[smallboard,setfen=##1]
        \skip_horizontal:n { \fill }
      }
    \par
  }

\cs_generate_variant:Nn \mychess_print_one_diagram_set:nn { nx }

% #1: 1 for the first series, 2 for second, etc.
\cs_new_protected:Npn \mychess_print_diagrams_for_series:n #1
  {
    \seq_map_inline:Nn \g_mychess_groups_seq
      {
        \mychess_print_one_diagram_set:nx
          {##1}                 % group name
          { \seq_item:cn { g_mychess_group_##1_seq } {#1} }
      }
  }

% Processing the “big structure”
\seq_new:N \g__mychess_rosfg_discovered_groups_seq

% #1: group name
% #2: data (a comma list: of rounds? Not sure about what the data represents)
\cs_new_protected:Npn \mychess_read_one_series_for_group:nn #1#2
  {
    \seq_if_in:NnF \g__mychess_rosfg_discovered_groups_seq {#1}
      { % First time we see group #1 in the “big structure”
        \seq_gput_right:Nn \g__mychess_rosfg_discovered_groups_seq {#1}
        % Clear all data for this group
        \seq_gclear_new:c { g_mychess_group_#1_seq }
      }

    % Append the data to what we already have for this group
    \seq_gput_right:cn { g_mychess_group_#1_seq } {#2}
  }

\cs_generate_variant:Nn \mychess_read_one_series_for_group:nn { VV }

\cs_new_protected:Npn \mychess_read_big_structure:n #1
  {
    \seq_gclear:N \g__mychess_rosfg_discovered_groups_seq

    \foreach \group / \data in {#1}
      { \mychess_read_one_series_for_group:VV \group \data }

    \seq_gset_eq:NN \g_mychess_groups_seq
                    \g__mychess_rosfg_discovered_groups_seq
  }

% #1: comma list of group names
\NewDocumentCommand \definegroups { m }
  {
    \mychess_define_groups:n {#1}
  }

% #1: group name
% #2: data for this group (a comma list containing one item per series, each
% item being itself a comma list describing the diagrams for the (group,
% series) combination).
\NewDocumentCommand \setgroupdiagrams { m m }
  {
    \mychess_set_group_diagrams:nn {#1} {#2}
  }

\NewDocumentCommand \readbigstructure { m }
  {
    \mychess_read_big_structure:n {#1}
  }

\NewDocumentCommand \printalldiagrams { }
  {
    \mychess_print_all_diagrams:
  }

\ExplSyntaxOff

\begin{document}

% Load the data as provided in the question
\readbigstructure{%
basic/{3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
basic/{3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
%******* PAWN LEVEL *****************
pawn/{8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
pawn/{8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
%************ 2 PAWN LEVEL *******************
2 pawns/{8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
2 pawns/{8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
%************ MINOR + PAWN LEVEL ********************
Minor + Pawns/{4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1},
Minor + Pawns/{4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1}}

% Print it
\printalldiagrams

\newpage
% Alternate input syntax written for the duplicate question:
% <https://tex.stackexchange.com/questions/497019/foreach-looping-error>
\definegroups{A, B, C, D}
\setgroupdiagrams{A}{
  {3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
   8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
   1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
  {3k4/8/2Q5/4K3/8/8/8/8 w - - 0 1,
   8/8/2k5/7R/6R1/8/5K2/8 w - - 0 1,
   1k6/7R/3K4/8/8/8/8/8 w - - 0 1},
}
\setgroupdiagrams{B}{
  {8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
   8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
   8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
  {8/8/8/8/8/1k6/7P/4K3 w - - 0 1,
   8/8/8/8/4k3/4p3/4K3/8 w - - 0 1,
   8/1k6/8/8/1PK5/8/8/8 w - - 0 1},
}
\setgroupdiagrams{C}{
  {8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
   8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
   k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
  {8/8/8/4p1K1/2k1P3/8/8/8 w - - 0 1,
   8/8/8/p7/P7/7k/7P/6K1 w - - 0 1,
   k7/P1K5/6p1/7p/7P/8/8/8 w - - 0 1},
}
\setgroupdiagrams{D}{
  {4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
   8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
   8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1},
  {4BK2/6P1/5k2/8/8/1b6/8/8 w - - 0 1,
   8/8/4k3/2p4n/2P1K3/8/7B/8 w - - 0 1,
   8/p7/P5p1/1P4P1/5P2/3kb3/8/3K4 w - - 0 1},
}
\printalldiagrams

\end{document}

Page 1

Page 1

(page 2 has the same diagrams as page 1 because the input data is the same)

Page 3

Page 3

(page 4 has the same diagrams as page 3 because the input data is the same)

Notes:

  • The alternate input syntax used the second time (see end of the document) declares group names A, B, C and D as in this duplicate question.

  • You can use \readbigstructure, \definegroups and \setgroupdiagrams before or after \begin{document}, it doesn't matter (these commands don't produce any output, contrary to \printalldiagrams).

If you want to learn expl3, the best starting point I know is expl3.pdf found here, then l3styleguide.pdf1 and finally the main reference, interface3.pdf. In any case, reading the TeXbook before will be of great help, because many essential TeX concepts2 are underlying everywhere in the LaTeX3 language. For instance, once you understand \edef, you'll know pretty well what x argument specifiers do and why they can't be used in such and such situations.


Footnotes:

  1. Very short; you may skip the Documentation style section at this point.

  2. In particular, character and category codes, tokens, how characters from the input are turned into tokens and how the resulting stream of tokens is processed (part of which is the concept of expansion), \edef, \csname and \string.

frougon
  • 24,283
  • 1
  • 32
  • 55
  • 1
    The awkward \cs_if_exist:cF construction should be replaced by \seq_clear_new:c { l_mychess_group_#1_seq } – egreg Jun 23 '19 at 09:20
  • @egreg Thanks for the hint, this is indeed nicer! I've updated the code to also be able to handle the precise input syntax used in the question (tailored for pgffor's \foreach, all the data declared in one block). – frougon Jun 23 '19 at 10:13
  • @frougon - Thank you so much for your codes. Greatly appreciated. Can you recommend resources so I can learn about this feature. I never know that Latex is also about programming. – user92127 Jun 24 '19 at 00:43
  • I was out of the house and am now back. I compile the code you provided and overleaf shows 86 error. Here's the project: https://www.overleaf.com/2711293339kwchqmcgjcwg – user92127 Jun 24 '19 at 01:09
  • @user92127 Okay, sorry but I have no account at overleaf. You can paste the log at for instance https://pastebin.com but since it all works fine here, I'd say it isn't likely to reveal a problem in the code. But at least it could allow us to rule out some kinds of “user error”. :-) Learning LaTeX programming is a long process. First you need to learn how to use LaTeX (LaTeX book by Leslie Lamport [useful when starting but a it dated], parts of the LaTeX Companion, online tutorials—see here)... – frougon Jun 24 '19 at 05:35
  • ... then progressively write macros to solve simple problems, that can become less simple with time. The programming resources that were useful to me are essentially those mentioned at the end of my answer, plus this site (invaluable!). The TeXbook (by D. Knuth) is extremely useful. You don't need to read everything to just do general programming, for instance you can safely skip the chapters on mathematical typography with TeX (unless your programming will be about producing equations with macros). But chapters about input processing, macros and paragraph breaking at least are a must IMHO. – frougon Jun 24 '19 at 05:39
  • “but a it dated” shoud have been written “but a bit dated” in my comment above. Likewise, in the TeXbook, you don't need to read the chapter on alignments unless you are going to program within tabular or similar environments (you can do some programming without reading it, but a few problems will seem mysterious until you read the actual rules used by TeX alignments in that chapter, rules that apply to tabular because it relies on the TeX primitive... – frougon Jun 24 '19 at 05:45
  • ... \halign). The TeXbook isn't very easy at first, the exercises are often tricky (many of them deal with special cases). But when you start reading it for the second time, it will become much clearer and you'll learn a lot. Plus, now there is this site to help when you find something unclear. It is really an invaluable source of information. – frougon Jun 24 '19 at 05:46
  • I finish my comment because I forgot one thing, but it's really off-topic for this question and you should see specialized questions (such as the one I linked above, maybe also that one) concerning the “learning” part. Just wanted to add that the TeXbook chapter on page breaking is also a must (except possibly the very end) because it concentrates most of the information on TeX registers (count, ... – frougon Jun 24 '19 at 06:02
  • ... dimen, skip, muskip, box and token list registers). Note: the LaTeX book by Leslie Lamport (full title: LaTeX: A Document Preparation System) can be useful to learn how to use LaTeX, but 1) as said, some parts are dated (BibTeX, makeindex, the picture environment: all these have more modern replacements nowadays: BibLaTeX + biber, xindy and TikZ or MetaPost) 2) it is way too superficial concerning the programming aspects (it shows how to write extremely simple macros, but nothing more). But it is a much easier reading than the TeXbook (they really aren't at the same level). – frougon Jun 24 '19 at 06:20
  • Concerning the errors at overleaf, if you don't manage to solve them, I'd suggest to install a real TeX distribution such as TeX Live or MikTeX on your computer. – frougon Jun 24 '19 at 06:26
  • @frougon - Thank you for your advice. I compile the code on TexStudio. Here is the paste.bin: https://pastebin.com/gF8N3kAm – user92127 Jun 24 '19 at 20:21
  • You mentioned problem solved. Does it you are able to get access to my project at overleaf.com/2711293339kwchqmcgjcwg ? When you compile, do you see the 86 errors ? – user92127 Jun 24 '19 at 20:33
  • It works without errors on TeX Live 2019 and gives the screenshots I posted. Your pastebin link only gives a small portion of the messages from a LaTeX run, which hints at a font installation problem (in my experience of user support, this has happened several times in the last months for MikTeX users—not with Skaks, but still font installation problems; I would try with TeX Live if you see no way to fix the installation). Concerning overleaf, as said, I have no account there, sorry. But their software is reportedly often outdated... – frougon Jun 24 '19 at 20:53
  • You are right. Tex Studio shows font installation errors. Overleaf shows different error. I will try to install Tex Live 2019. – user92127 Jun 24 '19 at 21:19