liste di token

  • Creatore
    Topic
  • #44721
    strolego
    Partecipante
      Up
      0
      Down
      ::


      A pagina 94 degli “Appunti di programmazione” di Enrico, vengono introdotte alcune macro per la manipolazione di liste, ma l’autore avverte che

      Si noti che le nostre manipolazioni permettono solo di stampare gli
      elementi della lista, non di passarli ad altre macro come argomenti

      C’è un modo per ottenere questa seconda cosa?
      Il mio problema è avere qualcosa del tipo (usando quelle macro e un comando del pacchetto geometry)
      `
      \buildlist{opzioni}{}
      \appendtolist{opzioni}{left=3cm}
      \appendtolist{opzioni}{right=2cm}
      …..
      \newgeometry{\opzioni} -> o qualcosa di simile…

      `

      Grazie
      Flavio

    Visualizzazione 9 filoni di risposte
    • Autore
      Risposte
      • #44722
        robitex
        Amministratore del forum
          Up
          0
          Down
          ::

          A pagina 94 degli “Appunti di programmazione” di Enrico, vengono introdotte alcune macro per la manipolazione di liste, ma l’autore avverte che

          Si noti che le nostre manipolazioni permettono solo di stampare gli
          elementi della lista, non di passarli ad altre macro come argomenti

          C’è un modo per ottenere questa seconda cosa?
          Il mio problema è avere qualcosa del tipo (usando quelle macro e un comando del pacchetto geometry)
          `
          \buildlist{opzioni}{}
          \appendtolist{opzioni}{left=3cm}
          \appendtolist{opzioni}{right=2cm}
          …..
          \newgeometry{\opzioni} -> o qualcosa di simile…

          `

          Grazie
          Flavio

          Per manipolare le liste io utilizzo il pacchetto etextools di Florent Chervet (pacchetto abbastanza recente che a sua volta estende il pacchetto di Lehman etoolbox, e nella fretta non riesco mai a non confondere il loro nome).

          Bye

        • #44723
          Up
          0
          Down
          ::

          A pagina 94 degli “Appunti di programmazione” di Enrico, vengono introdotte alcune macro per la manipolazione di liste, ma l’autore avverte che

          Si noti che le nostre manipolazioni permettono solo di stampare gli
          elementi della lista, non di passarli ad altre macro come argomenti

          C’è un modo per ottenere questa seconda cosa?
          Il mio problema è avere qualcosa del tipo (usando quelle macro e un comando del pacchetto geometry)
          `
          \buildlist{opzioni}{}
          \appendtolist{opzioni}{left=3cm}
          \appendtolist{opzioni}{right=2cm}
          …..
          \newgeometry{\opzioni} -> o qualcosa di simile…

          `

          Grazie
          Flavio

          `\expandafter\newgeometry\expandafter{\opzioni}`
          Ciao
          Enrico

        • #44724
          strolego
          Partecipante
            Up
            0
            Down
            ::

            `\expandafter\newgeometry\expandafter{\opzioni}`

            e se invece di \newgeometry avessi un comando con argomenti come (scusa la “bestemmia sul comando)

            \newgeomerty[arg1]{arg2}{arg3}[\lista]

            Non riesco a vedere dove vanno gli \expandafter
            🙁

            Proverò a guardare etextools e etoolbox anche se dai miei ricordi la documentazione non brillava per chiarezza e ricchezza di esempi

            Grazie
            Flavio

          • #44725
            Up
            0
            Down
            ::

            `\expandafter\newgeometry\expandafter{\opzioni}`

            e se invece di \newgeometry avessi un comando con argomenti come (scusa la “bestemmia sul comando)

            \newgeomerty[arg1]{arg2}{arg3}[\lista]

            Non riesco a vedere dove vanno gli \expandafter
            🙁

            Proverò a guardare etextools e etoolbox anche se dai miei ricordi la documentazione non brillava per chiarezza e ricchezza di esempi

            Perché non dire con chiarezza che ti serve?

            Se ti serve semplicemente un’interfaccia a \newgeometry (ma non saprei perché), puoi fare così:
            `\makeatletter
            \newtoks\st@collecttoks
            \newcommand*{\collectoption}[1]{%
            \st@collecttoks=\expandafter{\the\st@collecttoks,#1}}
            \newcommand*{\applynewgeometry}{%
            \expandafter\newgeometry\expandafter{\expandafter\@gobble\the\st@collecttoks}%
            \st@resettoks={}}
            \makeatother`
            A questo punto puoi dire
            `\collectoption{right=3cm}
            \collectoption{left=2cm}
            \applynewgeometry`
            che sarebbe equivalente a
            `\newgeometry{right=3cm,left=2cm}`
            Ciao
            Enrico

          • #44726
            strolego
            Partecipante
              Up
              0
              Down
              ::


              Scusami ho usato quel comando di geometry perché è stato il primo che mi è venuto in mente che operasse su una lista.

              Il mio problema è questo: devo scegliere casualmente da una lista di m oggetti (m diciamo 15) una lista di n (

            • #44727
              Up
              0
              Down
              ::

              Scusami ho usato quel comando di geometry perché è stato il primo che mi è venuto in mente che operasse su una lista.

              Il mio problema è questo: devo scegliere casualmente da una lista di m oggetti (m diciamo 15) una lista di n (

              Qualcosa del genere?
              `\documentclass[a4paper]{article}
              \usepackage{lcg}

              \makeatletter
              \g@addto@macro\r@nd{\global\cr@nd\cr@nd}

              \newcommand{\rchoice}[4][]{\begingroup\def\excl@list{#4}%
              \ifx\relax#1\relax
              \reinitrand[first=#2,last=#3]%
              \else
              \reinitrand[seed=#1,first=#2,last=#3]%
              \fi
              \def\xyz@{}%
              \@for\next:=\excl@list\do{\@namedef{xyz@\romannumeral\next}{}}%
              \count\z@=\z@
              \@rchoice\endgroup}
              \def\@rchoice{%
              \ifnum\count\z@=10 \else
              \expandafter\@dochoice
              \fi}
              \def\@dochoice{\rand
              \@ifundefined{xyz@\romannumeral\c@rand}{\@goodchoice}{\@rchoice}}
              \def\@goodchoice{\@namedef{xyz@\romannumeral\c@rand}{}%
              \advance\count\z@\@ne\number\c@rand\relax\space\@rchoice}
              \makeatother

              \begin{document}

              \rchoice[1]{1}{15}{2,3}

              \rchoice[1]{1}{15}{2,3}

              \rchoice{1}{15}{1,2,3,4,5}

              \end{document}`
              Ciao
              Enrico

            • #44728
              Up
              0
              Down
              ::

              Qualcosa del genere?

              Spiegazione.
              `\g@addto@macro\r@nd{\global\cr@nd\cr@nd}`
              Per motivi di implementazione, il comando \rand non funziona se chiamato dentro un gruppo. Così si risolve.

              `\newcommand{\rchoice}[4][]{\begingroup
              \ifx\relax#1\relax
              \reinitrand[first=#2,last=#3]%
              \else
              \reinitrand[seed=#1,first=#2,last=#3]%
              \fi`
              Il comando \rchoice ha tre argomenti obbligatori: il minimo, il massimo e la lista dei numeri da escludere. Per prima cosa inizializziamo il contatore dei numeri casuali; l’argomento opzionale è il seme. Ci mettiamo in un gruppo.

              ` \def\xyz@{}%
              \def\excl@list{#4}%
              \@for\next:=\excl@list\do{\@namedef{xyz@\romannumeral\next}{}}%`
              Per ogni elemento della lista di esclusione, che deve essere un numero, definiamo il comando \xyz@xii (se il numero è 12). Così possiamo sapere se il numero è fra gli esclusi o fra quelli già estratti, esaminando se \xyz@xii (o quello che è) è definito.

              ` \count\z@=\z@
              \@rchoice\endgroup}`
              Avviamo la ricorsione, tenendo conto di quanti numeri abbiamo estratto nel contatore 0 (tanto siamo in un gruppo).

              `\def\@rchoice{%
              \ifnum\count\z@=10 \else
              \expandafter\@dochoice
              \fi}`
              La macro \@rchoice è quella responsabile della ricorsione. Se abbiamo già raggiunto il numero di 10 estrazioni buone, abbiamo finito, altrimenti eseguiamo \@dochoice.

              `\def\@dochoice{\rand
              \@ifundefined{xyz@\romannumeral\c@rand}{\@goodchoice}{\@rchoice}}`
              La macro \@dochoice estrae un numero; se il numero è fra quelli esclusi o già estratti, eseguiamo ancora \@rchoice. Altrimenti eseguiamo \@goodchoice.

              `\def\@goodchoice{\@namedef{xyz@\romannumeral\c@rand}{}%
              \advance\count\z@\@ne\number\c@rand\relax\space\@rchoice}`
              La macro \@goodchoice definisce \xyz@xii (se il numero estratto è 12) o il comando opportuno. Poi avanza il contatore della ricorsione, stampa il numero estratto ed esegue di nuovo \@rchoice.

              Ciao
              Enrico

            • #44729
              strolego
              Partecipante
                Up
                0
                Down
                ::


                Grazie del codice (ma come fai a produrlo così di getto?)

                Ho trovato un’altra soluzione usando random (che uso già in altri punti). Così come è non permette la scelta del seme, ma la cosa mi interessa poco (e posso sempre aggiungerlo con \randomi=). La parte principale (\getitems) è un adattamento di un vecchio codice TeX trovato tempo fa in rete.

                Mi piacerebbe avere un tuo parere

                `
                \documentclass[a4paper]{article}
                \usepackage{ifthen}
                \input{random}
                \makeatletter
                \newcount\i@sh
                \newcount\j@sh
                \newcount\sh@max
                \newcounter{shuf@tot}
                \newcounter{shuf@lop}
                \newcommand\shuf@ch{}
                \renewcommand{\theshuf@lop}{\roman{shuf@lop}}

                %%% costruisco la lista
                \newcommand\shuf@ifch[2]{%
                \ifthenelse{\not\equal{\shuf@ch}{#1}}{\stepcounter{shuf@lop}\expandafter\edef\csname item\theshuf@lop \endcsname{#2}}{}%
                }

                \newcommand\es@item[1]{%
                \edef\es@Lista{\zap@space#1 \@empty}%
                \@for\shuf@ch:=\es@Lista\do{%
                \shuf@ifch{}{\shuf@ch}%
                }
                }

                \newcommand{\sh@chex}[1]{
                \setcounter{shuf@lop}{0}
                \renewcommand{\theshuf@lop}{\roman{shuf@lop}}
                \es@item{#1}
                \renewcommand{\theshuf@lop}{\arabic{shuf@lop}}
                \setcounter{shuf@tot}{\theshuf@lop}
                }

                \def\printitem#1{\csname item\romannumeral#1\endcsname}

                %%% la funzione di scelta nella lista #2 escludendo #1 elementi
                \newcommand{\scegli}[2][0]{\sh@max=#1\sh@chex{#2}\getitems}

                \def\getitems{%
                \i@sh=\theshuf@tot
                \loop
                \expandafter\let \csname flag\number\i@sh \endcsname a%
                \advance\i@sh by-1
                \ifnum\i@sh > 0 \repeat
                \i@sh=\theshuf@tot
                \loop
                \setrannum{\j@sh}{1}{\theshuf@tot}%
                \expandafter\ifx \csname flag\number\j@sh \endcsname a%
                \expandafter\let \csname flag\number\j@sh \endcsname b% Controllo se è già stato scelto
                \expandafter\edef\csname file\romannumeral\j@sh\endcsname{\csname item\romannumeral\i@sh\endcsname}
                \printitem\j@sh
                \advance\i@sh by-1
                \fi
                \ifnum\i@sh > \sh@max \repeat
                }

                \makeatother

                \begin{document}
                \scegli{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \scegli[3]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \scegli[16]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \end{document}
                `

              • #44730
                Up
                0
                Down
                ::

                Grazie del codice (ma come fai a produrlo così di getto?)

                Ho trovato un’altra soluzione usando random (che uso già in altri punti). Così come è non permette la scelta del seme, ma la cosa mi interessa poco (e posso sempre aggiungerlo con \randomi=). La parte principale (\getitems) è un adattamento di un vecchio codice TeX trovato tempo fa in rete.

                Mi piacerebbe avere un tuo parere

                `
                \documentclass[a4paper]{article}
                \usepackage{ifthen}
                \input{random}
                \makeatletter
                \newcount\i@sh
                \newcount\j@sh
                \newcount\sh@max
                \newcounter{shuf@tot}
                \newcounter{shuf@lop}
                \newcommand\shuf@ch{}
                \renewcommand{\theshuf@lop}{\roman{shuf@lop}}

                %%% costruisco la lista
                \newcommand\shuf@ifch[2]{%
                \ifthenelse{\not\equal{\shuf@ch}{#1}}{\stepcounter{shuf@lop}\expandafter\edef\csname item\theshuf@lop \endcsname{#2}}{}%
                }

                \newcommand\es@item[1]{%
                \edef\es@Lista{\zap@space#1 \@empty}%
                \@for\shuf@ch:=\es@Lista\do{%
                \shuf@ifch{}{\shuf@ch}%
                }
                }

                \newcommand{\sh@chex}[1]{
                \setcounter{shuf@lop}{0}
                \renewcommand{\theshuf@lop}{\roman{shuf@lop}}
                \es@item{#1}
                \renewcommand{\theshuf@lop}{\arabic{shuf@lop}}
                \setcounter{shuf@tot}{\theshuf@lop}
                }

                \def\printitem#1{\csname item\romannumeral#1\endcsname}

                %%% la funzione di scelta nella lista #2 escludendo #1 elementi
                \newcommand{\scegli}[2][0]{\sh@max=#1\sh@chex{#2}\getitems}

                \def\getitems{%
                \i@sh=\theshuf@tot
                \loop
                \expandafter\let \csname flag\number\i@sh \endcsname a%
                \advance\i@sh by-1
                \ifnum\i@sh > 0 \repeat
                \i@sh=\theshuf@tot
                \loop
                \setrannum{\j@sh}{1}{\theshuf@tot}%
                \expandafter\ifx \csname flag\number\j@sh \endcsname a%
                \expandafter\let \csname flag\number\j@sh \endcsname b% Controllo se è già stato scelto
                \expandafter\edef\csname file\romannumeral\j@sh\endcsname{\csname item\romannumeral\i@sh\endcsname}
                \printitem\j@sh
                \advance\i@sh by-1
                \fi
                \ifnum\i@sh > \sh@max \repeat
                }

                \makeatother

                \begin{document}
                \scegli{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \scegli[3]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \scegli[16]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,a,b,c}

                \end{document}
                `

                Mi pare che sia più o meno come il mio; c’è una parte davvero brutta:
                `\newcommand{\sh@chex}[1]{
                \setcounter{shuf@lop}{0}
                \renewcommand{\theshuf@lop}{\roman{shuf@lop}}
                \es@item{#1}
                \renewcommand{\theshuf@lop}{\arabic{shuf@lop}}
                \setcounter{shuf@tot}{\theshuf@lop}
                }`
                che, a parte la notevole quantità di spazi spuri, è inutilmente complicata:
                `\newcommand{\sh@chex}[1]{%
                \setcounter{shuf@lop}{0}%
                \es@item{#1}%
                \setcounter{shuf@tot}{\value{shuf@lop}}%
                }`
                Non occorre certo rappresentare numericamente un contatore per accedere al suo valore. 🙂

                Sinceramente preferisco il mio; si tratta solo di aggiungere una corrispondenza tra gli oggetti eterogenei del tuo insieme e un insieme numerico “fisso”, diciamo {1,2,…,n}, dove n è il numero totale di oggetti.

                Nella macro \@goodchoice invece di \number\c@rand che semplicemente stampa il risultato numerico, si può mettere una qualsiasi macro. Il modo più semplice è usare \csname per avere una “associative array”.
                `\def\make@list#1{%
                \count@=\z@ \def\temp{#1}
                \@for\next:=\temp\do{\advance\count@\@ne
                \expandafter\def\csname lista@\romannumeral\count@\expandafter\endcsname
                \expandafter{\next}}
                \chardef\listlength=\count@}
                %%% ridefinizione di \@goodchoice
                def\@goodchoice{\@namedef{xyz@\romannumeral\c@rand}{}%
                \advance\count\z@\@ne\do@something\@rchoice}
                %%% definizione dell'azione finale da eseguire con l'elemento estratto
                \def\do@something{\@nameuse{lista@\romannumeral\c@rand}\space}`
                Potresti adesso definire
                `\newcommand\scegli[1]{\make@list{#1}%
                \rchoice{1}{\list@length}{}}`
                Non sono ben sicuro di aver capito a che serve l’argomento opzionale di \scegli

                Ciao
                Enrico

              • #44731
                strolego
                Partecipante
                  Up
                  0
                  Down
                  ::


                  Grazie dei suggerimenti.

                  L’argomento opzionale di scegli serve a dare il numero di elementi da scartare.

                  Ciao
                  Flavio

              Visualizzazione 9 filoni di risposte
              • Devi essere connesso per rispondere a questo topic.

              Go to top