Как найти положение слова в беспорядочном предложении?

Как найти положение слова в беспорядочном предложении?

У меня есть начальное предложение:

Быстрая коричневая лиса прыгает через ленивую собаку.

У меня есть новое предложение (которое всегда представляет собой мешанину из исходного предложения):

Ленивая собака перепрыгивает через быструю коричневую лису.

В исходном предложении для каждого слова я хочу добавить надстрочный индекс позиции слова в соответствии с перемешанным предложением. Может ли кто-нибудь подсказать мне, как этого добиться?

Любой новый подход (использование новых пакетов) приветствуется. Спасибо заранее. В следующем MWE я, очевидно, не достигаю того, чего на самом деле хочу.

\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}

В этом примере я получу нужный мне результат, если вместо этого у меня будет следующее определение:

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

Желаемый результат

Но я не хочу вносить изменения вручную. Я ищу способ сделать его «динамичным» на основе перепутанного предложения.

РЕДАКТИРОВАТЬ: Я хочу добиться этого даже в таких сценариях:

Первоначальное предложение:

Быстрая коричневая лиса прыгает через ленивую собаку.

Спутанное предложение:

ленивая собака перепрыгивает через быструю коричневую лису.

В этом случае мне нужно иметь своего рода «теги» для слов в исходном предложении, чтобы перемешанное предложение было однозначным.

\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
}

Желаемый результат: Желаемый результат

решение1

На мой взгляд, самое интересное в TeX — это его набор текста, а самое худшее — его возможности программирования, поэтому лучше всего заниматься таким программированием вне TeX (как можно дальше!) и использовать TeX исключительно для набора текста. Все может бытьвозможныйс TeX, но это не обязательно будет самым простым/наиболее поддерживаемым решением.

Тем не менее, если вы используете TeX, то этот тип программирования проще реализовать с LuaTeX (по крайней мере, для меня, и я думаю, для большинства людей). Скомпилируйте следующий файл с помощью lualatex(я оставил ваши «теги» необязательными: вы можете пометить каждое слово как the(1) quick(2) ..., или пометить только дублирующиеся слова):

\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}

где jumble.lua(который можно было бы встроить в тот же .texфайл, но я предпочитаю хранить отдельно) находится следующее:

-- 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

Это производит

выход

как в вопросе.

Обратите внимание, что вы можете сделать это немного короче (например, см. первую редакцию этого ответа), перемещая элементы, но я считаю, что лучше всего сохранить (насколько это возможно) инструкции по набору текста .texи программирование в .luaфайле.

решение2

Что-то вроде этого?

\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}

введите описание изображения здесь

Связанный контент