Oletetaan, että haluaisin sensuroida kiroussanan <word>
käyttämällä grawlixes , esim ”Mitä # @ $! Teet ?!” Kuinka voin määrittää komennon \censor
siten, että \censor{<word>}
johtaa merkkijonoon näistä symboleista? En ole täysin varma, mitä tai kuinka monta symbolia tulisi käyttää sanalle <word>
. Oletan, että käytettyjen symbolien lukumäärän pitäisi olla suunnilleen yhtä suuri kuin merkkien lukumäärä sarakkeessa <word>
.
Kiitos panoksestasi!
Kommentit
- Se on paljon helpompaa tehdä tekstieditorilähteessä kuin TeX: ssä. (luatex on luultavasti helpompaa kuin klassinen tex, jos todella haluat tehdä sen tekstitasolla) (On tarpeeksi helppoa tehdä se rajoitetuissa tekstikonteksteissa, mutta vaikea, jos sinun on tehtävä se mielivaltaisissa kappaleissa ja luetteloissa jne.)
- katso myös tex.stackexchange.com/questions/88394/…
- @percusse I # @ $! &%? !% $ @!% $.
- @GonzaloMedina Voinko ostaa vokaalin?
- No, ainakin Olen oppinut uuden sanan tänään. Mutta miksi ’ t ei ole monikko grawlice ?
vastaus
Satunnainen symboli otetaan luettelosta ja liitetään merkkiluetteloon; kun kertyneiden symbolien leveys on suurempi kuin sanan miinus 2pt leveys, symbolit tulostetaan, muuten liitetään toinen symboli.
\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_censor:n { #1 } } \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \begin{document} Censored \censor{Censored} \end{document}
vastaus
nöyrä yritys lualatex
:
Korvaava koodi on hyvin naiivi, tarvitsemme jotain vankempaa.
\documentclass{article} \directlua{ % my list of bad words bad_words = { "fish", "cat", "dog", "horse", "alligator" } % the replacement string replacement = "duck" % a replacement function which returns % both the altered line and the number % of occurrences function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, replacement) end end return line, 0 end % my "naive" censor function, it simply % replaces any occurrences of the % list of bad words by the replacement % string function censor(line) occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end % add the hook callback.register("process_input_buffer", censor)} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document}
Lähtö:
Moraali tarina: Olen kauhea kertomaan tarinoita. :)
Lisää nyt grawlixit . Koska tarvitsen paremman Lua-koodin, luo ”s” ulkoisen tiedoston censor.lua
ja kutsu se ulos .tex
-koodista:
\begin{filecontents*}{censor.lua} -- a list of symbols to represent the -- grawlixe symbols -- note that we need to escape -- some chars grawlixe_symbols = { "\\$", "\\#", "@", "!", "*", "\\&" } -- generate a grawlixe of length s -- note that the seed is not so random, so -- same values of s might get the same -- grawlixe pattern (I could add another seed -- mid code, but I"m lazy) function grawlixe(s) math.randomseed(os.time()) local u = table.getn(grawlixe_symbols) local i = math.random(u) local r = grawlixe_symbols[i] local current local w = 1 repeat current = math.random(u) while current == i do current = math.random(u) end i = current r = r .. grawlixe_symbols[i] w = w + 1 until w == s return r end -- a list of bad words to be censored bad_words = { "fish", "cat", "dog", "horse", "alligator" } -- our replacement function, it returns -- the new line and the number of -- replacements made -- note that this is a very naive replacement -- function, there"s a lot of room for -- improvement function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, grawlixe(string.len(element))) end end return line, 0 end -- the censor function, it repeats -- ad nauseam until the line has -- nothing more to be censored function censor(line) local occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end -- register the callback callback.register("process_input_buffer", censor) \end{filecontents*} \documentclass{article} \directlua{dofile("censor.lua")} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document}
Lähtö:
Uuden tarinan moraali: grawlixien lisääminen tekstiin näyttää siltä tuhmalta. :)
Kommentit
- +1 (vaikka toivoin ankkakuvan, ehkä se sensuroitiin?)
Vastaus
Jättämällä hyvät ja huonot puolet siitä, miten ja miksi tämä tehdään, minusta on mukava pieni harjoitus, joka liittyy xstring
. Joten otan sen vastaan:
\documentclass{article} \usepackage{xstring} \def\grawlix{{\makeatletter@\makeatother}\textdollar{$\sharp$}*?!} \newcommand{\censor}[1]{\StrLen{#1}[\result]% \expandarg\StrLeft{\grawlix}{\result}[]} \begin{document} What the \censor{word} is this??? \end{document}
Kuten näette, rajoituksena on, että grawlix koostuu samoista merkistöistä samassa järjestyksessä. (Voit määrittää hahmoryhmän uudelleen tai löytää tavan satunnaistaa ne makron jokaisessa kutsussa … mutta se on erilainen tarina! ;)
) Mutta grawlixisi on yhtä pitkä sensuroituna sanana.
Tapahtuu, että xstring
: llä on omat tapansa laajentaa argumentteja eikä makroja voida sisäkkäin. Eli löydetyn makron tulos sensuroidun sanan pituus palautetaan eri makrossa (jota kutsutaan mielikuvituksellisesti täältä \result
), jota (uudelleen) käytetään ennalta määritellyn \grawlix
oikeaan kohtaan.
\expandarg
-makro varmistaa, että laajennus tehdään oikein. xstring
dokumentaatiota, se sallii kaikkien välitettyjen argumenttien laajentamisen täsmälleen kerran. Siksi on huolehdittava ryhmien, jotka edustavat yksittäistä merkkiä, suojaamisesta aaltosulkeilla (esim. \sharp
-symboli asuu mathmodessa, mutta emme halua t dollarin merkit, jotka rajoittavat sen katsottavan erillisiksi rahakkeiksi).
Kommentit
- En halua ’ Luulen, että
\makeatletter
ja\makeatother
ovat välttämättömiä @: n ympärillä … Sitä voidaan käyttää symbolina, joka on heti. - @cgnieder Se ’ sa hyvää työtä he eivät ole välttämättömiä, koska niillä ei ole mitään vaikutusta, jos niitä käytetään sisällä tässä määritelmässä: – )
- @DavidCarlisle true, en ollut ’ ajatellut sitä … Tarvitsen lisää kahvia
Vastaa
Tavallinen TeX-ratkaisu ilman lisäpaketteja, perustuu Kees van der Laanin ideoihin.
\documentclass{article} \begin{document} \newcount\cur \newcount\cura \def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi} \def\mynum#1{\cur\the\lccode`#1\relax\the\cur } \def\process#1{\cur\the\lccode`#1\relax\cura\cur \divide\cura by7 \multiply\cura by7 \advance\cur by-\cura\ifcase\cur!\or@\or\#\or\$\or\%\or\&\or*\else ERROR\fi } \fifo censored \ofif \bigskip \def\censor#1{\fifo #1\ofif} \censor{fuck} \censor{WORD} it is \censor{shit} \end{document}
Haluat todennäköisesti liittää tuloksen käytettyyn sanaan.Tässä ratkaisussa se on merkin moduuli 7 \lccode
. Voit kirjoittaa joko
\fifo censored \ofif
tai ehdotuksen mukaisesti (anteeksi kielestäni),
\censor{fuck} \censor{WORD} it is \censor{shit}
hankitaan
Joitakin selityksiä. Päätyökalu on Kees van der Laanin ehdottama FIFO (First-In-First-Out) -jono:
\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi}
\fifo
-komento kutsuu makron \process
, joka käsittelee yksittäiset argumentit. Jokaista tunnusta käsitellään \ofif
asti.
Loput ovat yksinkertaisia. Manipuloiminen laskureilla \cur
ja \cura
saadaan luku välillä 0 ja 6 ja \ifcase
vie eri sensuurimerkkejä eri arvoille.
Huomautus. Olen todella kiinnostunut todellisista säännöistä ( jos sellaisia on) korvata kiroussanat @ -merkkisillä merkkijonoilla.
Kommentit
- Erittäin mukava. Voisitko ehkä laajentaa (anteeksi sanaa) hieman siitä, miten koodi todella toimii?
- @AlanMunn Kyllä, mutta palattuasi kotiin (myöhään illalla).
-
\censor{MSWORD}
vastaus
Vakaa tapa vaihtaa symboleja on muuttaa fontkikoodausta tai koodaa fontti uudelleen. Yksinkertainen esimerkki
\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document}
Lualatexillä tulevaisuudessa (kun käyttöliittymä on vakaampi) on todennäköisesti mahdollista luoda virtuaalisia uudelleen koodattuja fontteja lentää, tällä hetkellä sen pitäisi olla jo mahdollista tehdä ominaisuustiedostolla.
vastaus
Tämä on laajennus @egreg ”s vastaukseen käyttämällä toista vastausta käyttäjältä @egreg.
Tällä koodilla voit kirjoittaa kokonaisen lauseen kohtaan \censor
ja kaikki alun perin luetteloon \addcensor
lisätyt sanat korvataan grawlixeillä. Argumentti \addcensor
voi olla joko yksittäinen sana tai pilkuilla erotettu luettelo.
\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_badseq:n { #1 } } \tl_new:N \g_pointer_badwords_tl \NewDocumentCommand{\addcensor}{m} { \clist_map_inline:nn { #1 } { \tl_gput_right:Nn \g_pointer_badwords_tl { {##1}{} } } } \cs_generate_variant:Nn \str_case:nnTF { nV } \cs_new_protected:Npn \pointer_badseq:n #1 { \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 } \seq_map_inline:Nn \l_tmpa_seq { \str_case:nVTF { ##1 } \g_pointer_badwords_tl { \pointer_censor:n { ##1 } } { ##1 } ~ % Readd space } \tex_unskip:D % Remove the trailing space } % From @egreg"s answer \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \addcensor{censored,duck} \addcensor{street} \begin{document} A censored man walk down the street together with his duck. \censor{A censored man walk down the street together with his duck}. \end{document}
Kommentit
- Se ärsyttää minua, kun käytät perinteistä avoimen sijoittamista ja sulkeutuva aaltosulkeus (avoin ahdin funktion vieressä, sitten uusi rivi, sitten koodi ja sitten yksin sulkeutuva aaltosarja uudella rivillä – ilman sisennystä), sekoittamalla se suositellun LaTeX3-tapaan (molemmat yksin uudella rivillä, sisennetty sama määrä tilaa).
- @Manuel Anteeksi, Toivon päivitetyn vastaukseni sopivan suositeltuun tyyliin.
- Ehdottomasti parempi (IMO). Pidän tällä tavalla, vaikka nyt ’ luen ConTeXt-lähdekoodia ja se kirjoittaa täysin eri tavalla (ainakaan he eivät käytä ’ aloitusmerkki, uusi viiva, koodi, uusi rivin sulkutuki ilman sisennystä liikaa, mutta jotain muuta
%
, uusi rivi, avaava ahdin ja koodi, lisää koodia ja sulkeutuva ahdin seuraavaksi koodiin).