Čtvrtá série dvacátého pátého ročníku KSP
Celý leták, který posíláme také papírově, v PDF.
I v této sérii můžete získat sladkou odměnu! Každému, kdo vyřeší
všechny vstupy v CodExu rychleji než vzorové řešení (a správně),
pošleme čokoládu.
Zadání úloh
Deníky japonského velvyslance v ČR p. Yamady. Dešifrováno a přeloženo v NSA
2023-11-15.
To byl zase den. Nakonec všechno dobře dopadlo, ale jsem opravdu vyčerpaný. Tak
vyčerpaný, že bych snad odložil dnešní zápis až na zítřek. Ale to bych měl
špatné spaní a vůbec bych si neodpočinul. Na tom doporučení psychologa něco
bude, vypsat se ze svých starostí. Tak tedy do toho.
Den začal jako každý jiný. Nějaké nepodstatné schůzky, podepisování, uklánění a
potřásání. Ti Evropané jsou divní. Tohle musí přispívat k šíření nemocí.
Pak ale přišlo první vytržení ze stereotypu. Kódovaná zpráva od jednoho kontaktu
u místní policie. Budu si muset promluvit se svými lidmi. Taková jednoduchá
šifra, primitivní prohazování písmen. Takto mi ty kontakty dlouho nevydrží,
někdo je určitě objeví.
25-4-1 Přesmyčky (10 bodů)
Každé slovo je zašifrované jako posloupnost písmen a číslo k. Písmena jsou ze
zašifrovaného slova, jen přeházená. Nalezněte původní slovo, což je k-tá
přesmyčka v lexikografickém pořadí z daných písmen. Například pro vstup
acb 3
je výsledkem
bac
, neboť přesmyčky v lexikografickém pořadí jsou:
abc acb bac bca cab cba
.
Pozor, písmena se mohou opakovat. V takovém případě jsou stejná
písmena nerozlišitelná, tedy třeba slovo aaa
má jedinou
přesmyčku, slovo baa
má přesmyčky tři, konkrétně aab aba
baa
.
Lehčí varianta (za 7 bodů): Vyřešte úlohu za předpokladu, že se písmena opakovat nemohou.
Řešení
Po dekódování se o mě však pokusil infarkt. Naštěstí jsem jej kratičkou meditací
zažehnal. Na víc než 5 minut jsem však čas neměl. Ve zprávě totiž stálo, že
policie má tip na jeden z mých skladů zboží a chystají dnes razii. Díky varování
mám naštěstí několik hodin náskok, začnu tedy plánovat, jak zachránit jak sklad,
tak své lidi.
Plán byl jednoduchý. Je to totiž prodejní sklad, takže má i místnost pro styk
s veřejností. A ta je maskovaná jako levné čínské bistro. Stačí tedy zboží
naložit a odvézt. Až dorazí policie, najde jen kuchařku a číšnice. Jediný háček
byl tedy v odvozu.
Má organizace má, samozřejmě, k dispozici dostatečné množství rychlých vozů. Pokud jsou ale
naložené, musí v zatáčce přibrzdit. A to zdržuje. A čím déle budou vozy na
cestě, tím větší je šance, že je někdo odhalí. Vzal jsem tedy mapu Prahy a začal
plánovat trasu s co nejméně zatáčkami.
25-4-2 Plánování trasy (9 bodů)
Představme si Prahu jako čtvercovou síť. Na některých políčkách stojí
překážky (budovy, policisté a podobně), těmi ostatními jde projíždět. Dále máme
na mapě vyznačeno startovní a cílové políčko. Obě tato políčka jsou průjezdná.
Vůz se vydá ze startovního políčka některým ze čtyř směrů a pokračuje stále
rovně, až kam to jde (tedy, kdyby pokračoval ještě jedno políčko, najel by na
překážku, případně by vyjel z mapy). Zde si opět vybere jeden ze
zbylých tří směrů a pokračuje, kam až to
jde. Tedy, nikdy není ochotný zatočit, pokud před sebou má volné místo. Pokud se
ocitne na cílovém políčku, zastaví se.
Nalezněte trasu, která obsahuje co nejméně zatáček. Z takových, pokud jich bude
víc, vyberte tu nejkratší.
Řešení
Po tak náročné činnosti jsem se šel projít na zahradu. Ale klid mi to
nepřineslo. Napřed tam dělali hluk ti zahradníci, co sekali zahradu. A všude
nechávali hrozně moc posekané trávy. Doufám, že se zítra nadřou při jejím
svážení. Oni si určitě budou chtít práci usnadnit, takže bych jim měl dát
za úkol posvážet trávu z nějaké části, kde to ani tak nebudou mít
příliš jednoduché. Pozorovat je při práci mi totiž zítra jistě zvedne náladu.
25-4-3 Rozpis svozu (13 bodů)
Trávník je obdélníkový a rozdělený na čtverce o straně 1 metr. Víme, kolik
posekané trávy se nachází na každém ze čtverců.
Jsou dány rozměry trávníku N, M. Dále dostaneme K oblastí
(určených svým levým horním a pravým dolním rohem). Chceme pro každou
z těchto oblastí určit nejmenší nutnou práci pro svoz trávy z celé
oblasti na nějaké jedno políčko.
Práce se spočítá jako hmotnost trávy na čtverci vynásobená
vzdáleností, kam se veze, s tím, že vozit smíme jen vodorovně nebo
svisle. Tedy vzdálenost mezi čtverci (0, 0) a (3, 4) je 7,
nikoliv 5.
Pro každou oblast určete políčko, kam trávu svézt, aby celková práce
byla nejmenší možná, a příslušné množství práce. Pokud existuje takových
nejlepších políček více, vypište libovolné z nich. Složitost
algoritmu optimalizujte pro případy, kdy K je řádově stejně velké
jako N.
Příklad: (První řádek obsahuje rozměry trávníku, dalších M řádků popisuje
hmotnosti trávy na jednotlivých čtvercích, pak následuje číslo K a K řádků
popisujících oblasti.)
3 5
8 2 1 5 3
6 9 1 2 7
1 1 3 2 10
3
1 1 3 3
3 2 5 3
2 1 4 2
Nejvýhodnější políčka s příslušnou prací jsou následující:
2 2 36
5 3 22
2 2 24
Poznámka: Pokud vám to připadá téměř jako
zadání úlohy 25-3-3, jen na dvojrozměrném trávníku, pak
máte zcela správný pocit.
Řešení
Než jsem stihl rozmyslet, kterou část jim vyberu, objevila se
mi tu nějaká ženská. Nepamatuji se, že bych takové kdy poskytl audienci a
rozhodně jsem to ani neplánoval. Ona však měla tolik drzosti, že se mě hned
začala vyptávat na mé soukromé obchody. A, považte, dokonce japonsky. Takové
neúcty bych se ve svém rodném Japonsku rozhodně nedočkal.
Bohužel, ve zdejších končinách není přípustné nosit samurajský meč a zastrašovat
jím drzé zvědavce. Nezbylo mi tedy než sáhnout po telefonu a požádat o laskavost
jednoho z mých věrných lidí u policie. Když jsem se tenkrát sázel se svým
čínským kolegou, kdo dokáže podplatit i posledního policistu, nikdy jsem
netušil, jak moc se to bude hodit.
25-4-4 Podplácení (8 bodů)
Policejní hierarchie je jakási pyramida. Úplně nahoře se nachází jeden kapitán.
Ten má k dispozici dva nadporučíky. Dále existují tři poručíci, čtyři
podporučíci, atd. až úplně dolů k řadovým policistům. Celá hierarchie
o výšce 7 je schematicky znázorněna jako příklad níže. Nedivte se, že někteří
policisté mají dva přímé nadřízené, v naší zemi je možné cokoliv.
V podplácení soutěží dva velvyslanci. Ten, který je na řadě, si vybere jednoho
policistu, který ještě nebyl podplacen, a předá mu zavazadlo
naplněné penězi. Tento policista obejde všechny své ještě
nepodplacené nadřízené (přímé i nepřímé) a peníze jim spravedlivě rozdělí. Tím
je podplatí. Takto by tedy vypadala hierarchie po jednom podplacení:
Vyhrává ten velvyslanec, který podplatí posledního policistu.
Pokud je zadaná výška celé hierarchie, určete, který z velvyslanců má
vyhrávající strategii. Začíná Japonec.
Řešení
A opravdu, po kratičké chvilce se objevil policista a zbavil mě jí. Asi jí začal
docela zatápět, což je jedině dobře. Po chviličce se zcela zřejmě pokusila
přechytračit policistu nějakým trikem s kalkulačkou. Nemínil jsem čekat na to,
až se jí to podaří, a raději jsem zmizel opět dovnitř. Už mi v kanceláři stačili
připravit čaj.
Jak jsem si tak sedal, uvědomil jsem si, že to byl úplně stejný typ kalkulačky,
na jaké jsem se učil vyššímu účetnictví. V tomto účetnictví bylo mnoho kliček a
triků, jak v něm schovat výdělky, do kterých nikomu nic není. Můj nejoblíbenější
byl ten, že úředníci neuměli počítat s velkými čísly, proto pracovali jen se
zbytky po vydělení svým inteligenčním maximem. To skýtalo opravdu mnoho
možností, jak je přimět si myslet, že vlastně nikdo nevydělal nic, a tedy že ani
nemá platit žádné daně.
25-4-5 Účetnictví (12 bodů)
Na začátku nemáme na účtu nic (svítí na něm tedy hezká 0). Budeme provádět
transakce po dobu k dní. V i-tém dni provedeme transakci v hodnotě i.
Umíme ovlivnit, jestli peníze přijdou na účet, nebo z něj odejdou.
Úředníci berňáku počítají mod n. Zvolme například n = 50.
Máme-li na účtu 20 Kč, můžeme si na něj nechat převést od kamaráda 30 Kč a berňák si
bude myslet, že nemáme nic. Kdybychom naopak z prázdného účtu kamarádovi 30 Kč odvedli,
skončíme s 20 korunami.
Zajímalo by nás, kolika způsoby můžeme rozvrhnout všechny transakce tak,
abychom na konci měli opět „prázdný“ účet. Počet způsobů ale roste velmi rychle,
stačí tedy počet „cest z nuly do nuly“ počítat modulo 109 + 7.
Tato úloha je praktická a řeší se ve vyhodnocovacím systému
CodEx.
Přesný formát vstupu a výstupu, povolené jazyky a další technické informace
jsou uvedeny v CodExu přímo u úlohy.
Řešení
Odpoledne se opět neslo ve znamení nepodstatných potřásání a uklánění. Tedy,
s výjimkou dvou telefonátů. Jeden mi sděloval, samozřejmě smluveným kódem, že se
přesun skladiště zdařil.
Druhý telefonát oznamoval radostnou zprávu, že nové zboží z domoviny zdárně
dorazilo. Samozřejmě, maskované jako skupinka turistů s foťáky. Můj nevlastní
bratranec z třetího kolena Mashiro je opravdu třída. Turisté nic netušili, a
dokonce jako maskování poslal i svého vlastního synovce. Jak jsem se nasmál,
když mi předevčírem vyprávěl na videohovoru, že se malý Tanaka tak moc těší.
Večer byl ale opět namáhavý. Obchodní jednání s jedním z klientů. Dožadoval se
množstevní slevy. Nakonec se mi takovou katastrofu podařilo zažehnat, ale jen
díky tomu, že jsem ho obehrál v prastarých japonských Triádách.
25-4-6 Triády (12 bodů)
Triády jsou karetní hra. Celá pravidla jsou komplikovaná, nám bude stačit jen
základní princip. Na stůl se vždy vyloží n karet. Každá karta nese k různých
vlastností (kde k může být velké) a každá vlastnost může mít jednu ze 3
různých hodnot.
Trojici vyložených karet nazveme triádou, pokud se v každé vlastnosti všechny
tři karty shodují, nebo se v ní navzájem liší. Pokud bude n = 4, k = 3 a
vyložené karty (1, 2, 3), (1, 2, 1), (1, 3, 2) a (1, 1, 3), tak potom
druhá, třetí a čtvrtá karta tvoří triádu. V první vlastnosti se shodují a ve
druhých dvou se liší.
Vaším úkolem je mezi zadanými kartami najít triádu, nebo zjistit, že mezi nimi
žádná není (samozřejmě rychleji než soupeř).
Řešení
Tak to by byl další namáhavý den. Pro jistotu musím ještě svůj deník
zašifrovat, aby se k němu nedostal někdo, kdo by jej mohl zneužít ve svůj
prospěch. Jak tak prohlížím to šifrovací zařízení s knoflíky, přemýšlím, jak
dlouho by někomu trvalo, než by vyzkoušel všechna možná hesla. Heslo se zadává
nastavením knoflíků do správných pozic. Na mé verzi je celých 20 knoflíků,
každý s 12 pozicemi. To by mohlo i takové NSA trvat aspoň 100 let, a tou dobou
už to nebude můj problém.
25-4-7 Šifrovací knoflíky (10 bodů)
Šifrovací zařízení na sobě má k otočných knoflíků a každý jde nastavit do n
různých pozic (knoflíky se chovají cyklicky, tedy je možné je protočit). Těmito
knoflíky se nastavuje šifrovací klíč, a to jak k zašifrování, tak poté
k dešifrování.
My klíč neznáme, proto bychom rádi vyzkoušeli všechny možnosti nastavení
knoflíků. Nechceme se však zdržovat, a proto chceme každý klíč nastavit právě
jednou. V jednom kroku umíme otočit jedním knoflíkem o jednu pozici.
Popište způsob, jak knoflíky otáčet, abychom nastavili každý klíč právě
jednou. Zároveň požadujeme, aby na konci byly knoflíky ve výchozích
pozicích.
Lehčí varianta (za 5 bodů): Vyřešte úlohu bez požadavku, aby se knoflíky vrátily
do výchozích pozic.
Řešení
V archivu NSA nalezl
Michal „vorner“ Vaner
25-4-8 TeXgramy (14 bodů)
Upozornění: Přesný vzhled vysázených konstrukcí je v PDF
verzi! Ve webové verzi mohou být různé nepřesnosti, zvláště u vzhledu
vysázených vzorců. Pokud si tedy chcete být jisti tím, jak něco vypadá,
sáhněte prosím po verzi v PDF.
Ve čtvrtém dílu seriálu o TeXu si ukážeme pokročilé programování.
Potkáte proměnné, podmínky, čtení souboru i zápis. Naučíme se, jak automaticky
číslovat nadpisy, tabulky, obrázky i cokoli jiného.
Čísla, rozměry a skipy
TeX nabízí uživateli 256 celočíselných registrů, ke kterým se přistupuje
primitivem \count
stejně jako ke \catcode
. S číselným registrem se
dá pracovat stejně jako s \catcode
, jen \count
má větší rozsah
(32bitové celé číslo se znaménkem).
Na ukládání rozměrů poslouží \dimen
. Je to ve skutečnosti také
celočíselný registr, jehož základní jednotkou je ovšem 1 sp
(1 pt = 65536 sp). TeX nepracuje s rozměry většími než 230 sp = 16384 pt, což je
něco přes 570 cm, takže by vám to do začátku mělo stačit, pokud zrovna
nenavrhujete billboard obludných rozměrů.
Registry typu \skip
pak slouží k ukládání pružných rozměrů
(s roztažností). Jejich omezení je stejné jako u pevných rozměrů.
Kromě vypisování primitivem \the
a přiřazení umí tyto typy registrů také
základní aritmetické operace. Primitivum \advance
například slouží ke sčítání.
\count0=1 % přiřaď 1 do \count0
\advance\count0 by 1 % zvyš o 1
\the\count0 % vysázej 2
\advance\count0 by -15 % sniž o 15
\the\count0 % vysázej -13
\dimen0=1in
\advance\dimen0 by 1cm
\the\dimen0 % vysázej 100.72273pt
Klíčové slovo by
je možno vynechat, ale pro přehlednost se hodí.
Celočíselné registry umí také celočíselně násobit a dělit, stejně tak rozměry a skipy.
\count0=30
\multiply\count0 by 5
\the\count0 % vysázej 150
\divide\count0 by 7
\the\count0 % vysázej 21
\skip0=1pt plus 2pt minus 3pt
\multiply\skip0 by 3
\the\skip0 % 3pt plus 6pt minus 9pt
Rozměry můžeme také násobit číselnou konstantou uvedenou před nimi (skipy ani
celočíselné konstanty ne). Pozor, pokud se použije skip tam, kde se očekává
rozměr, TeX mlčí jako hrob a jako rozměr vezme základní velikost skipu.
\dimen0=1pt
\skip0=\dimen0 plus 0.3\dimen0
\the\skip0 % 1pt plus 0.3pt
\dimen0=0.6\skip0
\the\dimen0 % 0.6pt
Pokud si ukázku opravdu spustíte, zjistíte, že některé vypsané rozměry nejsou
přesné. TeX je totiž počítá všechny celočíselně a zaokrouhluje. Nicméně
1 sp ≈ 5,36 nm, takže případné rozdíly jsou zanedbatelné (vlnová
délka viditelného světla je řádově 100 sp). Je však vhodné o zaokrouhlování
vědět.
Mnoho interních hodnot TeXu jsou čísla nebo rozměry; kompletní seznam můžete
najít v TeXbooku na straně 272 a následujících.
Přiřazení do všech registrů i interních hodnot je lokální v rámci skupiny,
není-li uvedeno primitivum \global
:
\dimen0=5pt\dimen1=\dimen0
\the\dimen0 \the\dimen1 % 5pt 5pt
{\dimen0=10pt\global\dimen1=\dimen0
\the\dimen0 \the\dimen1} % 10pt 10pt
\the\dimen0 \the\dimen1 % 5pt 10pt
Boxy
TeX poskytuje 256 boxových registrů. Můžete si do nich uložit libovolný hbox
nebo vbox a nad nimi pak provádět další operace. Přiřazení do boxu se provádí
primitivem \setbox
a jeho vysázení/použití primitivem \box
.
\setbox0=\vbox{Ahoj Karle\par Jak se máš?}
Něco mezi.\par
\box0 % Box s pozdravem se vloží sem.
Po použití primitiva \box
se registr vyprázdní. Pokud potřebujete, aby
tam box zůstal, použijte na to primitivum \copy
.
\def\fivetimes#1{{\setbox0\vbox{#1}%
\copy0\copy0\copy0\copy0\box0}}
TeX zná rozměry uloženého boxu. Dostanete se k nim (a dají se i změnit!) použitím
primitiv \ht
(výška), \dp
(hloubka) a \wd
(šířka).
\def\measure#1{{\setbox0\vbox{#1}%
(\the\ht0\ + \the\dp0) $\times$ \the\wd0}}
\def\nullbox#1{{\setbox0\vbox{#1}%
\ht0=0pt\dp0=0pt\wd0=0pt\box0}}
\quad R1\par
\setbox1\vbox{\hrule
\quad\quad R2\par
\quad\quad\quad R3\par\hrule}
\measure{\copy1}\par
\nullbox{\box1}
\quad\quad\quad\quad R4\par
\quad\quad\quad\quad\quad R5\par
Všimněte si, že takto nelze natahovat nebo smršťovat samotný obsah boxu. To
TeX neumí. (pdfTeX to ve skutečnosti umí, ale není to úplně přímočaré. Řekněte si kdyžtak na fóru o pohádku o transformačních maticích.)
Umí však předstírat, že box má jinou velikost, než je ta skutečná. Toho jste si
jistě všimli v příkladu. Možné využití jistě vymyslíte sami.
Rozbalování boxů
Čas od času je potřeba box rozbalit. Například si v boxu poskládáte kousek
stránky a chcete, aby se TeX mohl rozhodnout, že uprostřed něj zlomí stránku.
V takovém případě se vám můžou hodit primitiva \unvbox
a \unhbox
,
kterými se vloží obsah odkazovaného boxu. Pokud potřebujete, aby se box akcí
nevyprázdnil, použijte primitiva \unvcopy
nebo \unhcopy
.
Ještě vyšší liga je pak dělení vboxu primitivem \vsplit
:
% Do vboxu vložíme několik odstavců textu
\setbox0\vbox{...}
% Uřízneme z něj a vložíme prvních 10cm
\vsplit0 to 10cm
\hrule % například čára na oddělení
% Vložíme zbytek
\box0
Uříznutí obsahu z boxu se koná na rozhraní boxů uvnitř. Takže obvykle se
netrefíte přesně na rozměr. TeX zde používá naprosto stejný algoritmus jako
na lámání stránky (ten nás v hrubých rysech čeká příště). Dostanete tedy box
vysoký přesně zadaný rozměr se správně roztahanými mezerami.
Úmyslně zde píšu box. Následující konstrukce je totiž povolena:
% Do vboxu vložíme několik odstavců textu
\setbox0\vbox{...}
% Uřízneme z něj prvních 10cm do boxu 1
\setbox1\vsplit0 to 10cm
% ... a nakopírujeme dvakrát hned pod sebe
\copy1\box1
Pojmenované registry
Ve složitějším dokumentu je vhodné pojmenovat si proměnné, neboť mezi
očíslovanými boxy se dá jednoduše ztratit. K tomu slouží sada maker
\new...
. Povšimněte si rozdílu mezi prací s boxem a s číselnými
veličinami.
\newcount\pocitadlo
\newdimen\velikost
\newskip\guma
\newbox\krabicka
\pocitadlo = 5\relax
\the\pocitadlo
\velikost = 5mm
\the\velikost
\guma = 5cm plus 1cm minus 1cm
\the\guma
\setbox\krabicka\vbox{obsah boxu}
\copy\krabicka
\unvcopy\krabicka
\vsplit\krabicka to \velikost
\box\krabicka
Vypíše toto:
Plain TeX rezervuje některé registry pro svá makra a některé registry pro
vaše makra (přes \new...
). Pokud se vám nechce si rezervovat registr,
který používáte jenom jako dočasné úložiště někde uvnitř složitých maker, jsou
vám k dispozici registry s jednocifernými čísly. I na ně si však dejte pozor –
pokud se v takovém místě začne lámat stránka, nebo pokud je změníte globálně,
dočkáte se velmi nepříjemných překvapení.
Pokud si chcete být jisti, používejte vždy a na všechno pojmenované registry.
Podmínka
TeX nabízí sadu podmínek \if...
, které umožňují větvit kód a psát
mocnější makra. Nejprve si ukážeme možnosti, které nám TeX nabízí, a potom
detailně prozkoumáme, jak zpracovává zdrojový kód, který obsahuje podmínku.
\if
expanduje následující tokeny, dokud to jde. Pokud jsou ve výsledku
první dva tokeny stejné, je podmínka splněna. (\if aa
je pravda, \if ab
je lež)
\ifx
vezme dva následující tokeny bez expanze. Pokud jsou identické
(stejný znak, stejná kategorie, případně stejně definované makro nebo stejné
primitivum), je podmínka splněna. Tahle podmínka se hodí zvlášť ve chvíli, kdy
potřebujete detekovat například prázdný parametr:
\def\x#1{\def\p{#1}\ifx\p\empty...}
\ifnum
porovnává dvě čísla. Povolené operace jsou >
, <
a
=
, přičemž se také parametr expanduje; \ifnum\count1>5\xy
nemusí být
kompletní podmínka, neboť za pětkou může pokračovat číslo, tedy i \xy
za
pětkou bude expandováno (a případně i další makra).
\ifodd
je pravda, pokud je uvedené číslo liché.
\ifdim
porovnává dva rozměry analogickým způsobem
jako podmínka \ifnum
.
\ifvoid
, \ifhbox
nebo \ifvbox
detekuje, jestli je boxový
registr prázdný, zaplněný hboxem nebo vboxem. Jako parametr čte jedno číslo.
\ifhmode
, \ifvmode
, \ifmmode
a \ifinner
slouží ke
zjištění, v jakém módu zrovna jsme (horizontálním, vertikálním, matematickém,
případně vnitřním). První tři se vzájemně vylučují, čtvrtý je nezávislý
(podmínka \ifinner
je splněna, pokud jsme uvnitř explicitního vboxu,
hboxu, nebo uvnitř jednodolarové matematiky).
Také si můžete definovat vlastní podmínku makrem \newif
, kterou si pak
můžete přepínat dle libosti.
\newif\ifbagr % všechny podmínky mají začínat if
\bagrtrue % nastavím, že je podmínka splněna
\bagrfalse % nastavím, že podmínka není splněna
Ještě jsme ale neukázali kompletní syntaxi podmínky. TeX, když uvidí
\if...
, vyhodnotí podmínku a rozhodne se, jestli je pravdivá, nebo
nepravdivá. Pokud je pravdivá, bude pokračovat dále ve zpracovávání, dokud
nenajde \else
. Od této chvíle jen čte tokeny a zahazuje je, dokud
nenajde \fi
. TeX dodržuje uzávorkování podmínek, takže pokud je
v zahazovaném seznamu tokenů \if...
, zahodí i příslušné \fi
.
Pokud je podmínka nepravdivá, zahodí se všechno do \else
nebo
\fi
, co nastane dřív. Větev \else
je totiž nepovinná.
Dejte si pozor na to, že tokeny \if...
, \else
a \fi
ukončují například načítání čísla nebo rozměru. Není tedy možné napsat
\count\if... 5 \else 6\fi
apod. Podmínky ovšem nevytvářejí skupinu, jsou
tedy běžné například takovéto konstrukce:
\ifnum\count0>10
\def\next{...}
\else
\let\next\relax
\fi\next
Úkol 1 [4b]
Vymyslete, jak automaticky číslovat nadpisy. Definujte sadu maker pro tři
úrovně nadpisů. Makro nesmí brát za parametry nic jiného než text nadpisu.
Nadpisy se automaticky číslují (od jedné), čísla nadpisů nižší úrovně začínají
vždy od jedné po každém nadpisu vyšší úrovně.
Rozmyslete a vhodně ošetřete situaci, kdy bude text nadpisu příliš dlouhý,
takže se nevejde na řádek. V řešení úkolu se zkuste obejít bez primitiva
\global
.
Vzhledem k tomu, že už jste poměrně zkušení, připravte makra včetně vhodného
nastavení mezer a velikosti písma (vizte dále). Estetická
kvalita výstupu bude zahrnuta do hodnocení.
Soubory: Vstup a výstup
Během sazby je možno pracovat i s jinými soubory než tím vstupním. Je vhodné si
je nejprve pojmenovat, to se provádí makrem \newread
(pro vstup) a
\newwrite
(pro výstup). Přesněji řečeno, tímhle si pojmenujete ukazatel
na soubor. Jeden ukazatel nemůže zároveň ukazovat na vstup i výstup a jeden
soubor není možno otevřít zároveň pro čtení i pro zápis.
Soubor otevřete primitivem \openin
nebo
\openout
, pak je z něj možno číst nebo do něj zapisovat primitivem
\read
nebo \write
a nakonec je vhodné soubor zavřít primitivem
\closein
nebo \closeout
.
\newread\cti
\newwrite\pis
\openin\cti=in % in je jméno vstupního souboru
\openout\pis=out % out je jméno výst. souboru
\read\cti to \neco
\write\pis{\neco}
\closein\cti
\closeout\pis
Čtecí operace se odehrávají ihned, zapisovací však až ve chvíli, kdy se
definitivně skládá stránka. Pokud však vložíte před takovou operaci primitivum
\immediate
, provede se hned. Důvod je jednoduchý – občas potřebujete
při zapisování do souboru vědět, na které stránce nakonec skončí okolní text.
Primitivum \write
svůj argument před zapsáním kompletně expanduje;
potřebujete-li do výstupu propašovat přímo něco s backslashem (například pokud
budete ten soubor za chvíli vkládat primitivem \input
), předřaďte
\noexpand
.
Úkol 2 [4b]
Rozšiřte řešení úkolu 1 o sazbu obsahu. Tedy přidejte příslušná makra a
upravte stávající. Uvažujte sazbu obsahu na konci i na začátku, nezapomeňte
rozmyslet sazbu příliš dlouhých nadpisů (které se nevejdou na řádek obsahu,
takže bude potřeba je rozdělit) apod.
Obsah vypadá tak, že na každém řádku je na začátku číslo nadpisu, pak text
nadpisu a na konci řádku číslo stránky.
Pokud budete sázet obsah na začátku, počítejte s víceprůchodovým zpracováním
(na jeden průchod to nejde).
K vyřešení tohoto úkolu se bude hodit vědět, že číslo aktuální strany se
nachází v číselném registru jménem \pageno
.
Úkol 3 [6b]
Vytvořte makro \multicolumn{X}
, kterému předáte jako X
jedno celé
číslo. Všechno mezi „začátkem“ \multicolumn{X}
a
„koncem“ \endmulticolumn
bude
vysázeno v X
sloupcích stejné šířky vedle sebe (dohromady včetně mezer
dají šířku sazby mimo toto prostředí).
Mezi sloupci nechť je mezera, jejíž celkovou šířku bude určovat registr
\newdimen\multicolumngap
, uprostřed ní nechť je svislá čára oddělující sloupce
široká \multicolumnline
.
Předpokládejte, že výsledná sazba se vejde na jednu stránku, tedy neřešte
stránkový zlom. Vyhněte se načítání vnitřku prostředí do parametru makra.
\multicolumn
nechť prostředí inicializuje a \endmulticolumn
nechť
prostředí uzavře a vysází příslušný počet sloupců.
Za řešení, které bude zvládat jen X=2, dostanete maximálně 3 body.
Různé druhy písem
Primitivní metoda, jak pracovat s písmem, je načtení a použití jednoho fontu.
Konstrukcí \font\xyz=csr10
jste řídící sekvenci \xyz
ztotožnili
s použitím běžného počeštěného desetibodového patkového fontu z rodiny
Computer Modern.
Uvedená konstrukce může být doplněna ještě upřesněním typu at 15pt
, což
vezme původní vkládaný font a zvětší jej na uvedený rozměr.
Počeštěné fonty z rodiny Computer Modern se jmenují následovně:
Číslo u jména fontu udává základní velikost v bodech (pt).
U běžnějších fontů (csr
, csbx
) se obvykle dodávají i jiné základní
velikosti, neboť například v menších velikostech je font širší – fontům se
různě mění proporce, zvětšení fontu není prosté geometrické natažení.
Také je nutno poznamenat, že základní velikost fontu není velikost písmenek.
Obvykle se jedná o součet maximální výšky a maximální hloubky písmene.
Rozsah dodávaných fontů záleží na distribuci a na balíkách, které máte
nainstalované. V případě CM fontů navíc existuje tzv. Sauterova parametrizace,
to je generátor všech základních velikostí v rozsahu cca 2 pt až 50 pt.
Běžná instalace csplainu obsahuje obvykle font csr velikostí 5, 6, 7, 8, 10, 12 a 17.
Po nastavení fontu je také potřeba správně nastavit některé další hodnoty,
typicky \baselineskip
.
Matematické fonty zůstávají nedotčeny; pokud potřebujete měnit i velikost písma
v matematice, zkuste se podívat do TeXbooku (od strany 153) nebo do TBN
(sekce 5.3), případně použít nějaký sofistikovaný systém, třeba OFS.
Olšákův systém fontů (OFS)
Pokud potřebujete seriózně pracovat s fonty a nechce se vám zabíhat do detailů,
je vhodné použít nějaký balík, který práci s fonty abstrahuje. Osobně doporučím
prostudovat dokumentaci k OFS.
Je to velmi chytře napsaný a mocný systém, který sám běžně používám v sazbě a
který používáme i v KSP.
Jan „Moskyto“ Matějka
Pokud i v sobě máte výtvarného ducha, budeme rádi, pokud ho také probudíte :-)
Řešení