BI-EP2 Efektivní programování 2 LS 2017/2018 Ing. Martin Kačer, Ph.D. 2011-18 Martin Kačer Katedra teoretické informatiky Fakulta informačních technologií České vysoké učení technické v Praze Vznik předmětu byl podpořen FRVŠ v rámci projektu 2581/2011
Detekce tvaru obrazců v trojúhelníkové mřížce 2
1. Určení řady 2. Pozice v dané řadě Point convert(int num) { int x = 0, n = 1; while (n + x < num) n += ++x; return new Point(x, num - n); } 0,0 1,0 1,1 2,0 2,1 2,2 3,0 3,1 4,0 4,1 4,2 3,2 5,0 5,1 5,2 5,3 4,3 3,3 5,4 4,4 5,5 3
Arrays.sort(vert, 0, ncnt); if (ncnt == 3) System.out.println(testTriangle()? RES_TRI : RES_NONE); else if (ncnt == 4) System.out.println(testParallelogram()? RES_PAR : RES_NONE); else if (ncnt == 6) System.out.println(testHexagon()? RES_HEX : RES_NONE); else System.out.println(RES_NONE); 4
Nezapomenout všechny možnosti Seřazení to zjednodušuje Kosočtverce: 5
Délka a počet nejkratších cest v šestiúhelníkové mřížce 6
Problém č.1 souřadnicový systém 25 24 23 22 26 11 10 9 21 12 3 2 8 20 13 4 1 7 19 14 5 6 18 36 30 15 16 17 35-1,-2 0,-2 1,-2 2,-2 3,-2-1,-1 0,-1 1,-1 2,-1 3,-1-2,0-1,0 0,0 1,0 2,0 x -2,1-1,1 0,1 1,1 2,1-3,2-2,2-1,2 0,2 1,2 y 7
První krok určení kruhu 1. Pole 1 2. Pole 2 až 7 (6 polí) 3. Pole 8 až 19 (12 polí) 4. Pole 20 až 37 (18 polí) 5. Pole 38 až int circ = 1, n = 2; while (num >= n + 6*circ) n += 6 * circ++; int rest = num - n; 25 24 23 22 26 11 10 9 21 12 3 2 8 20 13 4 1 7 19 14 5 6 18 36 30 15 16 17 35 8
Druhý krok souřadnice v rámci kruhu circ 25 24 23 C-1, -C 22 circ -2 26-1, -C+1 11 10 9 21-1 12 3 2 8 20 C, -1 0 13 4 1 7 19 1 14 5 6 18 36 2 2 30 15 16 17 35-2 -1 0 1 9
Druhý krok souřadnice v rámci kruhu if (rest < circ) { x = circ; y = -1 - rest; } else { rest -= circ; if (rest < circ) { x = circ-1 - rest; y = -circ; } else {... circ 25 24 23 C-1, -C 22 circ -2 26-1, -C+1 11 10 9 21-1 12 3 2 8 20 C, -1 0 13 4 1 7 19 1 14 5 6 18 36 2 2 30 15 16 17 35-2 -1 0 1 10
Třetí krok vzdálenost dx dy ( 0) 11
Určení vzdálenosti: jsou 3 možnosti 1 dy 2 3 12
Určení vzdálenosti: jsou 3 možnosti a) dx < -dy dy polí doprava nahoru -dy-dx polí nahoru -dx b) -dy dx 0 dy-(-dx) polí doprava dolů -dx polí doprava nahoru dy dy -dx c) dx > 0 dy polí doprava dolů dx polí dolů dx dy 13
Čtvrtý krok: počet cest Struktura cesty: A polí jedním směrem B polí druhým směrem Směry lze střídat libovolně A B => Kombinační číslo comb(a+b, A) = (A+B)! / A! / B! 14
Čtvrtý krok: počet cest BigInteger comb(int xd, int yd) { BigInteger res = BigInteger.ONE; for (int i = 1; i <= xd+yd; ++i) B res = res.multiply(biginteger.valueof(i)); A for (int i = 1; i <= xd; ++i) res = res.divide(biginteger.valueof(i)); for (int i = 1; i <= yd; ++i) res = res.divide(biginteger.valueof(i)); return res; Struktura cesty: A polí jedním směrem B polí druhým směrem Pořadí lze kombinovat } => Kombinační číslo comb(a+b, A) = (A+B)! / A! / B! 15
Implementace dlouhých čísel Výběr vhodné soustavy Desítková? Dvojková? Řád 10000?? Operace jako na papíře 16
17
Kolik políček s vodou je dostupných z povrchu Záplavové vyplňování (zde doslova ) 3D struktura Každá krychlička má (maximálně) 6 sousedů Spustíme postupně pro vše v horní vrstvě Počítáme zaplněné krychličky 18
while (qb < qe) { if (qx[qb] > 0) enqueue(qx[qb]-1, qy[qb], qz[qb]); if (qx[qb] < x-1) enqueue(qx[qb]+1, qy[qb], qz[qb]); if (qy[qb] > 0) enqueue(qx[qb], qy[qb]-1, qz[qb]); if (qy[qb] < y-1) enqueue(qx[qb], qy[qb]+1, qz[qb]); if (qz[qb] > 0) enqueue(qx[qb], qy[qb], qz[qb]-1); if (qz[qb] < z-1) enqueue(qx[qb], qy[qb], qz[qb]+1); ++qb; } 19
......*......*****...****......*2***...**1***......*****...***1**......***2*...****......*****...*............***...******......**2****...*4**4*......*******...******.....****2**...*4**4*......***...******...... 20
Určení počtu souvislých oblastí => Záplavové vyplňování Dvě úrovně zanořené do sebe 1. Vyplňuji kostku detekuji tečky 2. Najdu tečku a. započítám a vyplním tečku b. nahradím ji kostkou!! c. pokračuji ve vyplňování kostky 21
Jedno vyplňování uvnitř druhého => Potřebujeme dvě oddělené fronty Dvě samostatné metody 1. Nahrazování # za tečky 2. Nahrazování X za # Každá pracuje se svojí frontou a svými znaky Jedna univerzální metoda Nahrazovaný znak a frontu dostane jako parametr 22
class Queue { int[] qx = new int[r*c], qy = new int[r*c]; int qb = 0, qe = 0; } int enqueue(queue q, int i, int j, char rep) { if (i < 0 i >= r j < 0 j >= c) return 0; if (map[i][j] == rep map[i][j] == CH_BACK) return 0; int dot = 0; if (rep == CH_BACK && map[i][j] == CH_DOT) { dot = 1; replace(i, j, CH_DICE); } map[i][j] = rep; q.qx[q.qe] = i; q.qy[q.qe++] = j; return dot; } 23
24