뒤죽박죽된 문장에서 단어의 위치를 ​​찾는 방법은 무엇입니까?

뒤죽박죽된 문장에서 단어의 위치를 ​​찾는 방법은 무엇입니까?

초기 문장이 있습니다.

날렵한 갈색여우는 게으른 개를 뛰어넘는다.

나는 새로운 문장을 가지고 있습니다 (항상 원래 문장이 뒤죽박죽입니다):

게으른 개는 날렵한 갈색 여우를 뛰어넘는다.

원래 문장에서 각 단어에 대해 뒤죽박죽된 문장에 따라 단어 위치를 위첨자로 표시하고 싶습니다. 누군가 내가 이것을 달성할 수 있는 방법을 안내해 줄 수 있습니까?

새로운 패키지를 사용하는 모든 새로운 접근 방식을 높이 평가합니다. 미리 감사드립니다. 다음 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

IMO에서 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}

여기에 이미지 설명을 입력하세요

관련 정보