¿Cómo encontrar la posición de una palabra en una oración desordenada?

¿Cómo encontrar la posición de una palabra en una oración desordenada?

Tengo una frase inicial:

El rápido zorro marrón salta sobre el perro perezoso..

Tengo una oración nueva (que siempre es una mezcla de la oración original):

El perro perezoso salta sobre el veloz zorro marrón..

En la oración original, para cada palabra, quiero superponer la posición de la palabra según la oración mezclada. ¿Alguien puede guiarme sobre cómo puedo lograr esto?

Se agradece cualquier enfoque novedoso (utilizando nuevos paquetes). Gracias de antemano. En el siguiente MWE, obviamente no logro lo que realmente quiero.

\documentclass[12pt]{memoir}
\usepackage{listofitems}
\usepackage{amsmath}

\newcommand{\wordsI}
{   1. The,
    2. quick,
    3. brown,       
    4. fox      
    +
    5. jumps,
    6. over,
    7. the,
    8. lazy,
    9. dog
}

\newcommand{\wordsII}
{   The
    lazy
    dog         
    jumps
    over
    the
    quick
    brown
    fox
}

% Tokenize the words in order to display them
\newcommand{\tokenize}[1]
{%
    \setsepchar{+/,/./}
    \readlist*\textarray{#1}
    \foreachitem\groupoflines\in\textarray
    {
        \setsepchar{,}
        \readlist*\linearray{\groupoflines} 
        \foreachitem\line\in\linearray
        {  
            \setsepchar{.}
            \readlist*\wordarray{\line}
            $ \text{\wordarray[2]} ^ {\wordarray[1]} $
        }%
        \newline
    }
}

\begin{document}
\noindent
Actual sentence:
\newline
% The splitting of the sentence in 2 lines is intentional
\tokenize{\wordsI}

\noindent
Jumbled sentence:
\textbf{\wordsII}   
\end{document}

En este ejemplo, obtendré el resultado que necesito si tengo la siguiente definición:

\newcommand{\wordsI}
{   1. The,
    7. quick,
    8. brown,       
    9. fox      
    +
    4. jumps,
    5. over,
    6. the,
    2. lazy,
    3. dog
}

La salida deseada

Pero no quiero realizar el cambio manualmente. Estoy buscando una manera de hacerlo "dinámico" basándose en la oración confusa.

EDITAR: Quiero lograr esto incluso en escenarios como este:

Frase inicial:

El veloz zorro marrón salta sobre el perro perezoso..

Frase confusa:

el perro perezoso salta sobre el veloz zorro marrón.

En este caso, necesito tener algún tipo de "etiquetas" para las palabras de la oración inicial para que la oración confusa no sea ambigua.

\newcommand{\wordsI}
{   1. the,
    2. quick,
    3. brown,       
    4. fox      
    +
    5. jumps,
    6. over,
    7. the,
    8. lazy,
    9. dog
}

\newcommand{\wordsII}
{   7. the
    8. lazy
    9. dog         
    5. jumps
    6. over
    1. the
    2. quick
    3. brown
    4. fox
}

Salida deseada: Salida deseada

Respuesta1

En mi opinión, lo más interesante de TeX es su composición tipográfica y lo peor es su facilidad de programación, por lo que es mejor realizar dicha programación fuera de TeX (¡lo más lejos posible!) y usar TeX únicamente para la composición tipográfica. todo puede serposiblecon TeX, pero no será necesariamente la solución más fácil ni más fácil de mantener.

Aún así, si usas TeX, este tipo de programación es más fácil de hacer con LuaTeX (al menos para mí, e imagino que para la mayoría de las personas). Compile el siguiente archivo con lualatex(he dejado que sus "etiquetas" sean opcionales: puede etiquetar cada palabra como the(1) quick(2) ...o etiquetar solo las palabras duplicadas):

\documentclass[12pt]{memoir}
\usepackage{amsmath} % For \text

\newcommand{\printword}[2]{$\text{#1} ^ {#2}$\quad} % Or whatever formatting you like.
\newcommand{\linesep}{\newline}

\directlua{dofile('jumble.lua')}
\newcommand{\printjumble}[2]{
  \directlua{get_sentence1_lines()}{#1}
  \directlua{get_sentence2_words()}{#2}
  %
  \noindent
  Actual sentence:
  \newline
  \directlua{print_sentence1_lines()}

  \noindent
  Jumbled sentence:
  \textbf{\directlua{print_sentence2()}}
}

\begin{document}
\printjumble{
  the(1) quick brown fox
  +
  jumps over the(7) lazy dog
}{
  the(7) lazy dog jumps over the(1) quick brown fox
}
\end{document}

donde jumble.lua(que podría estar incluido en el mismo .texarchivo, pero prefiero mantenerlo separado) es el siguiente:

-- Expected from TeX: before calling print_sentence1_lines(),
--     call get_sentence1_lines() and get_sentence2_words()
--     define \printword and \linesep.
-- Globals: sentence2_words, position_for_word, sentence1_lines

function get_sentence1_lines()
   sentence1_lines = token.scan_string()
end

function get_sentence2_words()
   local sentence2 = token.scan_string()
   sentence2_words = {}
   position_for_word = {}
   local i = 0
   for word in string.gmatch(sentence2, "%S+") do
      i = i + 1
      assert(position_for_word[word] == nil, string.format('Duplicate word: %s', word))
      sentence2_words[i] = without_tags(word)
      position_for_word[word] = i
   end
end

function print_sentence2()
   for i, word in ipairs(sentence2_words) do
      tex.print(word)
   end
end

function print_sentence1_lines()
   for line in string.gmatch(sentence1_lines, "[^+]+") do
      for word in string.gmatch(line, "%S+") do
         position = position_for_word[word]
         assert(position_for_word[word] ~= nil, string.format('New word: %s', word))
         tex.print(string.format([[\printword{%s}{%s}]], without_tags(word), position))
      end
      tex.print([[\linesep]])
   end
end

function without_tags(word)
   local new_word = string.gsub(word, "%(.*%)", "")
   return new_word
end

Esto produce

producción

como en la pregunta.

Tenga en cuenta que puede hacer esto un poco más corto (por ejemplo, vea la primera revisión de esta respuesta) moviendo las cosas, pero me parece más limpio mantener (tanto como sea posible) las instrucciones de composición tipográfica en el .texarchivo y la programación en el .luaarchivo. .

Respuesta2

¿Algo como esto?

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\seq_new:N \l_jsp_sentence_temp_seq
\seq_new:N \l_jsp_sentence_original_seq
\seq_new:N \l_jsp_sentence_jumbled_seq
\prop_new:N \l_jsp_sentence_original_ind_prop
\prop_new:N \l_jsp_sentence_jumbled_ind_prop
\int_new:N \l_jsp_sentence_word_int

\NewDocumentCommand{\parseoriginalsentence}{m}
 {
  \seq_set_split:Nnn \l_jsp_sentence_temp_seq { + } { #1 }
  \seq_clear:N \l_jsp_sentence_original_seq
  \prop_clear:N \l_jsp_sentence_original_ind_prop
  \seq_map_inline:Nn \l_jsp_sentence_temp_seq
   {
    \int_zero:N \l_jsp_sentence_word_int
    \clist_map_inline:nn { ##1 }
     {
      \int_incr:N \l_jsp_sentence_word_int
      \seq_put_right:Nn \l_jsp_sentence_original_seq { ####1 }
      \prop_put:Nnx \l_jsp_sentence_original_ind_prop
       { ####1 } { \int_to_arabic:n { \l_jsp_sentence_word_int } }
     }
    \seq_put_right:Nn \l_jsp_sentence_original_seq { + }
   }
 }
\NewDocumentCommand{\parsejumbledsentence}{m}
 {
  \prop_clear:N \l_jsp_sentence_jumbled_ind_prop
  \seq_set_split:Nnn \l_jsp_sentence_jumbled_seq { , } { #1 }
  \int_zero:N \l_jsp_sentence_word_int
  \seq_map_inline:Nn \l_jsp_sentence_jumbled_seq
   {
    \int_incr:N \l_jsp_sentence_word_int
    \prop_put:Nnx \l_jsp_sentence_jumbled_ind_prop
     { ##1 } { \int_to_arabic:n { \l_jsp_sentence_word_int } }
   }
 }

\NewDocumentCommand{\printoriginalsentence}{s}
 {
  \IfBooleanTF{#1}
   {
    \jsp_sentence_print_from_original:
   }
   {
    \jsp_sentence_print_from_jumbled:
   }
 }

\cs_new_protected:Nn \jsp_sentence_print_from_original:
 {
  \seq_map_inline:Nn \l_jsp_sentence_original_seq
   {
    \tl_if_eq:nnTF { ##1 } { + }
     {
      \par
     }
     {
      \prop_item:Nn \l_jsp_sentence_original_ind_prop { ##1 }.\nobreakspace ##1 ~
     }
   }
 }

\cs_new_protected:Nn \jsp_sentence_print_from_jumbled:
 {
  \seq_map_inline:Nn \l_jsp_sentence_original_seq
   {
    \tl_if_eq:nnTF { ##1 } { + }
     {
      \par
     }
     {
      \prop_item:Nn \l_jsp_sentence_jumbled_ind_prop { ##1 }.\nobreakspace ##1 ~
     }
   }
 }
\ExplSyntaxOff

\begin{document}

\parseoriginalsentence{
  The,
  quick,
  brown,
  fox
  +
  jumps,
  over,
  the,
  lazy,
  dog
}
\parsejumbledsentence{
  The,
  lazy,
  dog,
  jumps,
  over,
  the,
  quick,
  brown,
  fox
}

\printoriginalsentence*

\bigskip

\printoriginalsentence

\end{document}

ingrese la descripción de la imagen aquí

información relacionada