User:Lukas Mach/Docasne uloziste


 * Here's how I think is proven, that it runs in O(Sqrt(|V|)*|E|) (we've done this in school..., it's slightly more general case) You have graph G(V, E), G is bipartite. Denote vertices from "left" partition L and vertices from the "right" one R. Also add source vertex s (and connect source s by edge to every vertex in L) and target t (and connect it to every vertex in R) just like you would if you'd be trying to solve bipartite matching using maximum flow (because that's exactly what this algorithm does). The orientation of every edge is from s to t ("from left to right"). Capacity of each edge is 1. Now you run Dinic algorithm on this input. Note that for each vertex v the following is true: min{deg+(v),deg-(v)} <= 1 (input or output degree of each vertex has degree of 1 or 0). We want to find better estimate on the number of iteration of Dinic alogrithm. We will take a look at k-th iteration. Note that after each iteration, the computed flow will grow at least by 1. Also, after each iteration the length of the shortest path grows by at least 1. So after k-th iteration, the length is >= k. This means that we can take graph G(V, E) and draw it in k layers (just like in BFS). Remember that Dinic algorithms in each iteration adds flow consisting from only shortest st-paths. (Thus we can ommit edges going from layer a to layer b (where a > b), but I don't think this is really essential at this point.) We know that current computed flow is at least k. If the value of final flow is K, then there are at most K - k iterations left. So we would like to give an estimate of the flow in residual network ("how much is still left?"). We can say that we have m edges in graph (m = |E|) and thus there is cut with at most m/k edges (because we have m edges and k layers). Since they all are of capacity 1, we can say that in residual network there is a cut of m/k capacity and thus the algorithm will perform a total of k + m/k iterations of the outer loop. So let k = Sqrt(m) and we have proven that the algorithm will end in O(Sqrt(m)) iterations of the outer loop. The inner loop has time complexity of O(m) (but only if every edge has capacity of 1, you have to check that every edge of the graph will be "touched" at most once in every interation of the outer loop), so this makes the running time of the whole thing O(Sqrt(m)*m). Whooops... not good enough! We'd be much happier with O(Sqrt(n)*m). The only thing we have to change, however, is to give a better estimate on the size of st-cut in residual network after k-th iteration. So, we will use the fact that every vertex has input or output degree of at most 1. We have k layers and n vertices. Thus, there is a layer with at most n/k vertices. We will form the cut in this way: if the input degree of some vertex v from this layer is 1, then add the edge entering this vertex, if it is greater than 1 then the output degree of v must be 1 and we will add to our cut the edge leaving v. This will form a cut of at most n/k edges and thus there will be at most n/k additional iterations of the outer loop of Dinic algorithm and implying total amount of k + n/k interations. Let k = Sqrt(n) and we have O(Sqrt(n)*m) running time of whole thing.

Práce se soubory
Vytvoření souboru:

touch novy_soubor       # vytvori soubor novy_soubor touch jean paul sartre  # vytvori 3 soubory: "jean", "paul", "sartre" touch jean\ paul\ sartre # vytvori 1 soubor: "jean paul sartre" touch jean\\\ \ \ \ paul # vytvori 1 soubor: "jean\   paul"

touch "./mark evans"    # dalsi zpusob jak dostat do nazvu mezeru touch './mark evans'    # ten samý výsledek

touch "./\\"            # vytvori soubor s nazvem \ (\ je escapovaci znak) touch './\\'            # vytvori soubor s nazvem \\ (apostrofy rusi vyznam \) touch "./a\ b"          # vytvori soubor s nazvem "a\ b" (\ je sice escapovaci retezec, ale                          # specialni vyznam mezery zrusily uz uvozovky)

touch 'slash/dot'       # neprojde


 * Příkaz touch nastaví existujícímu souboru čas poslední úpravy na současnost, pokud soubor neexistuje, pokusí se ho vytvořit. Pokud neuspěje, oznámí to na chybovém výstupu (něco jako touch: test/t: Permission denied).

Dost divný příklad:

echo 'xxxx-xxxx-xxxx-xxxx' | sed 's/x/abcdefghabcdefgh/g' | xargs touch   #neprojde


 * Vypíše File name too long. Řetězec xxxx-xxxx-xxxx-xxxx se pošle sedu, ten vezme každý z 16ti znaků x, nahradí ho řetězcem abcd..., následně to převezme příkaz xargs, který vezme standardní vstup a použije ho jako parametry příkazu touch, který spustí. Pokoušíme se tak vytvořit soubor se jménem dlouhým 259 znaků. Podobné vylomeniny s příkazem sed jsou popsány o kus dál.

Vytvoříme soubor, ve kterém je slovo ahoj:

echo ahoj               # vypise na obrazovku ahoj nasledovany znakem noveho radku echo ahoj | tee ./my    # vypise na obrazovku ahoj (zase s newline) a zaroven to hodi # do souboru "my" echo ahoj > ./my        # do souboru my ulozi ahoj (a newline) echo ahoj >> ./my       # pripoji k souboru retezec ahoj (cili ted to tam bude 2x,                         # kazdy na samostatnym radku) echo -n ahoj > ./my     # za retezec nepripoji newline, cili je to presne to, co jsme # chteli (a nic vic)

Zapsat do souboru 3 řádky (po zadání prvního řádku se objeví prompt 2)

echo 'prvni druha treti' | tee ./soubor

Vzít text každé řádky z tohoto souboru a vytvořit prázdný soubor s takovým jménem. Elegantní řešení:

xargs touch < ./soubor


 * xargs vezme standardní vstup a doplní ho jako argumenty příkazu, který sám dostane jako argument (viz slide 41 z přednášek). Což ale nedělá přesně to, co jsme chtěli. Pokud budou na řádcích mezery, povede každé slovo k vytvoření nového souboru. Navíc xargs neprojde, pokud uvnitř nebudou správně spárovány uvozovky a apostrofy. My přitom chceme vytvořit jména přesně identická s textem na řádku, nějaké speciální významy znaků nás nezajímají. Takže to zkusíme přes sed:

sed 's/\(.*\)/touch '\\1'\/' ./soubor | sh


 * Sed překonvertuje každý řádek na příkaz (z řádku "prvni" udělá "touch 'prvni'"), rourou to pošleme do sh a příkazy se vykonají.

Ještě jednou ten příkaz v sedu:

's /  \(.*\)  /  touch '\  \1'\   / '      # tohle sedu pošleme přes shell s /  \(.*\)  /  touch '\1'  /              # tohle sed dostane potom, co to znásilní shell

Pokud ale bude nějaký řádek obsahovat uvozovky, moc se to nepovede. Uvozovky na řádcích bychom měli odescapovat. Tj. uvozovku ( ' ) nahradíme třemi uvozovkami a za první dáme backslash ( '\'' ). Nakonec to teda bude:

sed "s/'/'\\\\''/g;s/\(.*\)/touch '\1'/" ./soubor | sh


 * Změnil jsem apostrofy za uvozovky, aby se líp vkládaly apostrofy do příkazů sedu.

Když se teď má na výstupu skutečně objevit backslash, musí být uveden 4x (protože to je escapovací znak shellu i sedu, viz předchozí výpis). Sed nakonec dostane:

s / ' / '\\'' /  g  s /  \(.*\)  /  touch '\1'  / 


 * Flag g na prvním řádku značí, že má být substituce provedena u všech výskytů apostrofu, ne jen u prvního, jak by to bylo bez flagu g.

head a tail
Odseknout od souboru vsechno po 5. radce (a ulozit to do toho sameho souboru). Jmeno souboru je dejme tomu ./in:

head -5 ./in > ./in    # spatne
 * Nebude fungovat, patrne proto, ze v jednu chvili neni mozne nekam zapisovat a zaroven to cist headem. Vysledek bude prazdny soubor (alespon u me).

Vypsat 3-6 radek souboru
Jde i pres tail, ale sedem to je:

sed -n '3,6p' ./in

Vypsat vsechno krome 3-6 radku souboru
sed -n '3,6!p' ./in

Prekvapive koukam jde i:

sed -n '3,6!!!p' ./in

Vypsat vsechny radky souboru zacinajici znakem #
Grepem:

grep '^#' /etc/passwd

Sedem hloupě:

sed -n 's/^#/#/p' < /etc/passwd
 * -n znamena "nic normalne nevypisuj"
 * flag p znamena "matchlo-li, vypis"

Sedem:

sed -n '/^#/p' < /etc/passwd
 * tohle p uz je prikaz, ne flag prikazu s (imho)

Vypsat useky uvedene mezi dvema radky, kde oba obsahuji jen a pouze radu #####
sed -n '/^###*$/,/^###*$/ p' /etc/passwd

Vypsat prihlasovaci jmena uzivatelu
Reseni 1 - pres sed:

sed 's/\([^:]*\).*/\1/' < /etc/passwd

Je ale lepsi jeste vyhodit radky zacinajici #:

sed -n '/^#/!s/\([^:]*\).*/\1/p' /etc/passwd

Vypsat skutecna jmena uzivatelu
Jednoduse pres cut:

cut -sd: -f5 /etc/passwd
 * Coz ale predpoklada, ze v odkomentovanych radcich neni dvojtecka.

Ciste sedem:

sed -n '/^#/!s/[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*/\1/p' /etc/passwd

Kombinace:


 * 1) grepem

grep -v '^#' /etc/passwd | cut -sd: -f5


 * 1) nebo sedem

sed -n '/^#/!p' /etc/passwd | cut -sd: -f5

Věci na prozkoumání

 * echo ahoj > tee ./my2
 * jak dostat na radku ruzne ASCII znaky? (solved)
 * touch \-d (patrne jasne)