IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Ondrej Zadrapa:5.6.2020 22:21

Caute, mam prosbu, mam vytvořit program na vypsani všech prvočísel od 1 do 1000, coz po nejake době hledani vyslo asi nejidealnejsi pouzit Erathosthenovo sito, jenomze tim, ze se ucim programovat ve VB, tak mi to praci pomerne stezuje, proste jsem to zkusil tady ze stranky prepsat z C do VB, ale bez uspechu.

Zkusil jsem:

Sub Main()
        Dim cisla(1000) As Integer, i As Integer, j As Integer
        For i = 2 To cisla.Length - 1
            cisla(i) = 1
        Next
        For i = 2 To Math.Sqrt(cisla.Length - 1)
            If cisla(i) = 0 Then
                Continue For
            End If
            For j = 2 * i To cisla.Length - 1
                cisla(j) = 0
            Next
        Next
        For i = 2 To cisla.Length - 1
            If cisla(i) = 1 Then
                Console.Write(i & " ")
            End If
        Next
        Console.ReadKey()
    End Sub

Tady na strankach jsem nasel 3 varianty, jedna v C, druha v Jave, treti v C#, tak jsem po dobrych zkušenostech s prepisu z C vyzkousel i ted, co to udela, ale vystup vypise pouze 2 a 3, coz je dobry start, ale do 1000 daleko.

Chci docílit: Abych bud pomoci tohoto algoritmu, nebo i jakkoli jinak byl schopen vypsat všechna prvočísla od 1 do 1000. Predem diky

 
Odpovědět
5.6.2020 22:21
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 0:24

Proč to odněkud přepisovat, když si to můžeš sám napsat. Celé to navíc lze poskládat z naprosto běžných řídících příkazů. Zde je pro jednoduchost ukázka bez použití optimalizací.

#include <stdio.h>

#define MIN 1
#define MAX 1000

int main(void){
        for (int num = MIN; num <= MAX; num++){
                int isPrime = 1;
                for (int i = 2; i <= num / 2; i++){
                        if (num % i == 0){
                                isPrime = 0;
                                break;
                        }
                }
                if (isPrime && (num > 1)) printf("%d ", num);
        }
        return 0;
}
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
6.6.2020 0:24
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Ondrej Zadrapa
David Flieger:6.6.2020 7:43

Chybu máš ve vnořeném cyklu s iterační proměnnou j. V něm přiřadíš všem číslům větším, nebo rovno 2*i nulu. Já bych to zkusil přepsat takto:

For j = 2 To cisla.Length / i
    cisla(i * j) = 0
Next

Tohle by mělo přiřadit nulu všem přirozeným násobkům nalezeného prvočísla i.

Další věc není chyba, ale způsob jak se vyhnout zbytečným řadkům. Jak máš

If cisla(i) = 0
     Continue For
End If

Tak bych změnil podmínku na cisla(i)=1 a v těle bych nechal ten for cyklus s iterační proměnnou j.

 
Nahoru Odpovědět
6.6.2020 7:43
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 10:16
Sub Main()
        Dim min(1) As Integer, max(1000) As Integer
        For num = min.Length To max.Length - 1
            Dim prvocislo As Integer = 1
            For i = 2 To num / 2
                If num Mod i = 0 Then
                    prvocislo = 0
                End If
                If prvocislo + num > 1 Then
                    Console.Write(num & " ")
                End If
            Next
        Next
        Console.ReadKey()

Nevim si s tim rady, VB nemá break, navíc mi to v mem podani vypise uplne všechny cisla.

 
Nahoru Odpovědět
6.6.2020 10:16
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 12:00

MIN a MAX jsou makra. Nahlížej na to jako na celočíselné konstanty. Není to pole, nemá žádnou délku, pouze hodnotu. Jednoduše na místo kde se nachází MIN a MAX se dosadí místo toho adekvátní hodnota.

řádek:

for (int num = MIN; num <= MAX; num++){

odpovídá:

for (int num = 1; num <= 1000; num++){

Znovu podotýkám, jsou to prosté celočíselné konstanty. Proto v žádném případě přepis do VB nemůže být následující:

For num = min.Length To max.Length - 1

Mělo by to být něco v tomto smyslu:

For num As Integer = 1 To 1000

VB má pro ukončení z cyklů jiný příkaz, ale má. Ve VB se pro ukončení cyklu For používá:

Exit For

Pro další ukončovací příkazy

EXIT STATEMENT

Nakonec podmínka výpisu prvočísla je tvořena logickým součinem

if (isPrime && (num > 1)) printf("%d ", num);

Kdežto ve tvém případě se jedná o součet dvou celočíselných operandů

If prvocislo + num > 1 Then

Je třeba užít logický součin

AND
Nahoru Odpovědět
6.6.2020 12:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 14:03
Sub Main()
       For num = 1 To 100
           Dim prvocislo As Integer = 1
           For i = 2 To Math.Sqrt(num)
               If num Mod i = 0 Then
                   Exit For
               End If
               If prvocislo And num > 1 Then
                   Console.Write(num & " ")
               End If
           Next
           Console.WriteLine()
       Next
       Console.ReadKey()

Vypise to od 5ky všechny cisla o 2 vetsi az do 1000, cisla se opakuji, nevim proc, nerozumim tomu.

Editováno 6.6.2020 14:03
 
Nahoru Odpovědět
6.6.2020 14:03
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 14:09

Vypisuješ čísla na nesprávném místě, je třeba vypisovat mimo for cyklus. Dále ti chybí nastavování převodovka na 0.

Nahoru Odpovědět
6.6.2020 14:09
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 14:21

Fu, teda, je to fuska, ale uz to dela, co ma, diky.

 
Nahoru Odpovědět
6.6.2020 14:21
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 14:36

Prosim Te, mam vypsat 10 radku, kdy na prvním radku bude 1, na druhem 12, na tretim 123. Mam k tomu vyuzit vnorenou smycku. Co si z toho mam vyvodit, ze po me profesor chce? Z toho jsem uplne jelen.

 
Nahoru Odpovědět
6.6.2020 14:36
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 14:45

Proč fuška? Stačí vědět co který úsek programu dělá a znát možnosti jazyka a umět je využít. Výpis prvočísla mimo cyklus musel být proto, aby se před tím dalo zjistit, zda skutečně prvočíslem je. Bylo třeba zapotřebí provést X iterací. Buď všechny kdy číslo je prvočíslem nebo zkráceně pomocí Exit For kdy číslo není prvočíslem neboť se našel dělitel beze zbytku a další iterace jsou už tak zbytečné.

Nahoru Odpovědět
6.6.2020 14:45
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 14:48

Chce po tobě cyklus uvnitř cyklu (konkrétně for uvnitř for), podobně jako by si vypisoval 2D pole. U prvního cyklu určuje řídící proměnná konkrétní řádek, u druhého cyklu určuje řídící proměnná aktuálně vypisované číslo.

Nahoru Odpovědět
6.6.2020 14:48
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 14:57
Sub Main()
        For i As Integer = 1 To 10
            For j As Integer = 1 To 10
                Console.Write(j & " ")
            Next
            Console.WriteLine()
        Next
        Console.ReadKey()
    End Sub

Cili něco takového ano? Jdu spravnym smerem?

 
Nahoru Odpovědět
6.6.2020 14:57
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 15:00

Jdeš správným směrem, ale rozsah druhého cyklu závisí na řídící proměnné prvního cyklu. Takto Ti to vypíše tabulku, která ale není v souladu se zadáním. Nemůžeš vypisovat 10 hodnot pro první řádek když máš vypsat pouze jednu hodnotu.

#include <stdio.h>

#define ROWS 10

int main(void) {

        for (int i = 1; i <= ROWS; i++) {
                for (int j = 1; j <= i; j++) printf("%d", j);
                putchar('\n');
        }

        return 0;
}
Nahoru Odpovědět
6.6.2020 15:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 15:06
Sub Main()
        For i As Integer = 1 To 10
            For j As Integer = 1 To i
                Console.Write(j & " ")
            Next
            Console.WriteLine()
        Next
        Console.ReadKey()
    End Sub

A vystup je

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10

Co zas delam spatne? :D

 
Nahoru Odpovědět
6.6.2020 15:06
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 15:08

Nyní to máš správně, tohle se po tobě chce. Zda má být mezera mezi čísly či nikoli je už jen otázkou formátování.

Nahoru Odpovědět
6.6.2020 15:08
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 15:09

Jo tak, ty blaho, ja jsem fakt kokot, to zadani je zavadejici, ja to bral jako cela cisla. :D :D :D :D No do prcic, Ti ucitele mají smysl pro humor. :D

Editováno 6.6.2020 15:11
 
Nahoru Odpovědět
6.6.2020 15:09
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 15:13

Ne? já bych řekl že jo... Jestli to chceš mít přesně tak vypisuj samotnou proměnnou j bez mezery, jak už jsem zde výše napsal. K tomu už nelze víc dodat..

Nahoru Odpovědět
6.6.2020 15:13
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 15:20

Ne, všechno v pohode, to jenom me nenapadlo, ze kdy je napsane 1, potom 12, potom 123, tak je to na jeden radek 1, další radek 1,2, ten další 1,2,3, atd...

 
Nahoru Odpovědět
6.6.2020 15:20
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 15:40

To už jsou detaily. Je ovšem třeba být důsledný a řídit se přesně tím co je napsáno. Zde to nevadí, ale jsou programy které využívají jako vstup výstup jiného programu a tam už si nemůžeš dovolit upravovat výstup dle libosti.

Tři hlavní body:

  • Umět pochopit zadání a řídit se tím co se požaduje.
  • Umět si v hlavě dokázat představit způsob jak to řešit.
  • Umět si v hlavě dokázat sestavit a vidět výsledný zdrojový kód.
Nahoru Odpovědět
6.6.2020 15:40
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 17:48

Tak jsem se dostal k dvojrozměrnému poli a chtěl bych se zeptat, jak muzu zobrazit radkove a sloupcove indexy bunek, na kterých se minimum nachazi? Nebo jinak, splnil jsem úkol podle zadani, nebo jsem proste akorát vypsal, kde se to minimum nachazi? Placnu, ze místo toho mělo byt, ze se nachazi 2 indexu 3 radku a na 3 indexu 2 sloupce.

Sub Main()
        Dim pole(,) As Integer = {
        {6, 8, 6, 4},
        {5, 15, 7, 8},
        {9, 3, 11, 12},
        {13, 14, 15, 16}
        }
        Dim minimum As Integer = pole(0, 0)
        Dim poradiI As Byte = 0
        Dim poradiJ As Byte = 0
        For i = 0 To pole.GetLength(0) - 1
            For j = 0 To pole.GetLength(1) - 1
                Console.Write(pole(i, j) & " ")
                If pole(i, j) < minimum Then
                    minimum = pole(i, j)
                    poradiI = i + 1
                    poradiJ = j + 1
                End If
            Next
            Console.WriteLine()
        Next
        Console.WriteLine("Minimum: {0} nalezneme v {1}. radku a {2}. sloupci", minimum, poradiI, poradiJ)
        Console.ReadKey()
    End Sub
 
Nahoru Odpovědět
6.6.2020 17:48
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 18:08

Pozice v 2D poli je jasně daná. Pokud např. minimum bude na pozici pole[1,2], pak říkáme, že X index má hodnotu 1, Y index má hodnotu 2. Je to totéž, jako bychom řekli že minimum se nachází na pozici řádku č. 2 a sloupce č. 3 (z důvodu toho že indexace pole začíná od nuly).

Od klasického 1D pole se to nijak neliší, je akorát přidán další rozměr. A interpretace 2D pole se vytváří vnořeným for cyklem do jiného for cyklu. Řídící proměnná vnějšího for představuje pozici řádku, řídící proměnná vnitřního for představuje pozici sloupce.

Nahoru Odpovědět
6.6.2020 18:08
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 19:51

Muzu se Te zeptat, jak docilim toho, abych dokazal vypsat pozice všech lokálních maxim v poli, cili kazde číslo, které vlevo i vpravo ma nižší hodnotu?

Sub Main()
        Dim pole(,) As Integer = {
            {10, 20, 3, 4},
            {5, 16, 8, 6},
            {4, 12, 25, 3},
            {0, 18, 16, 2}
        }
        Dim maximum As Integer = pole(0, 0)
        For i = 0 To pole.GetLength(0) - 1
            For j = 0 To pole.GetLength(1) - 1
                If pole(i, j) > maximum Then
                    maximum = pole(i, j)
                    Dim poradi1 = i
                    Dim poradi2 = j
                    Console.WriteLine("Cislo {0} na pozici ({1},{2})", maximum, poradi1, poradi2)
                End If
            Next
        Next
        Console.ReadKey()

Vypise mi to jen 2 cisla, jak to?

 
Nahoru Odpovědět
6.6.2020 19:51
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 20:14

Pokud lpíš striktně na tom, že lokální maximum je dáno vyšší hodnotou nebo stejnou než na pozici vlevo a vpravo, pak to docílíš tak, že vezmeš druhý až předposlední prvek v poli a každý tento prvek porovnáš s hodnotou na indexu vlevo a vpravo. Pokud bude vyšší, pak se jedná o lokální maximum a hodnotu vypíšeš, v opačném případě se o lokální maximum nejedná a pokračuješ n další index. Pokud chceš zahrnout i možnost, že lokální maximum může být první a poslední prvek a jeho hodnota je vyšší než prvek následující u prvního a předcházející u posledního, pak je toto možné udělat také tak, že pro první index provedeš test, poté vnitřní indexy a nakonec poslední. Tyto testy můžeš udělat i po vnitřních testech, ale už nemáš seřazena maxima od začátku pole, respektivě si je musíš ukládat a až nakonec vypsat. To v případě, kdy provedeš test prvního, následovaný testy vnitřními a nakonec posledním, nemusíš. Můžeš maxima vypisovat "za letu".

Nahoru Odpovědět
6.6.2020 20:14
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 20:32

Zde máš řešení pro určení lokálních maxim v 1D poli.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 20

int main(void) {
        int nums[SIZE];

        srand((unsigned int)(time(NULL)));

        // naplneni pole nahodnymi hodnotami v rozsahu 0-99
        for (int i = 0; i < SIZE; i++) nums[i] = rand() % 100;

        // kontrolni vypis pole (hodnota a index)
        for (int i = 0; i < SIZE; i++) printf("%d[%d] ", nums[i], i);
        putchar('\n');

        // test lokalniho maxima prvniho prvku
        if(nums[0]>nums[1]) printf("%d[%d] ", nums[0], 0);

        // test lokalniho maxima vnitrnich prvku
        for (int i = 1; i < (SIZE - 2); i++) {
                if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i + 1])) {
                        printf("%d[%d] ", nums[i], i);
                }
        }

        // test lokalniho maxima posledniho prvku
        if (nums[SIZE-1] > nums[SIZE-2]) printf("%d[%d] ", nums[SIZE-1], SIZE-1);

        return 0;
}

Výstup programu:

92[0] 64[1] 68[2] 29[3] 4[4] 83[5] 80[6] 21[7] 36[8] 33[9] 26[10] 11[11] 41[12] 34[13] 74[14] 57[15] 43[16] 70[17] 58[18] 91[19]
92[0] 68[2] 83[5] 36[8] 41[12] 74[14] 70[17] 91[19]
Nahoru Odpovědět
6.6.2020 20:32
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 20:41

No, zrejme Ti moc nerozumim, jak to myslis s temi prvky, něco jako:

If pole(0,1) And pole(2,2) > maximum Then
maximum = pole(i,j)
poradi1 = i
poradi2 = j

Ja v tom mam ted docela zmatek

 
Nahoru Odpovědět
6.6.2020 20:41
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 21:16

Podívej se na příklad který jsem Ti napsal pro určení lokáních maxim v 1D poli. Podívej se jak je tam řešeno porovnání sousedních hodnot. Všimni si, že si nikam neukládám indexy ani hodnoty, vše vypisuji "za letu".

if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i + 1])) {
        printf("%d[%d] ", nums[i], i);
}

Slovy řečeno:
Je-li hodnota na indexu i větší nežli hodnota na indexu i-1 (předchozím) a zároveň je-li hodnota na indexu i větší nežli hodnota na indexu i+1 (následujícím) pak vypiš hodnotu na indexu i jelikož se jedná o lokální maximum.

If pole(0,1) And pole(2,2) > maximum Then
maximum = pole(i,j)
poradi1 = i
poradi2 = j

Úryvek kódu který si uvedl je v mnoha ohledech chybný.

První chybou je že hodnoty ve 2D poli vůbec spolu nesousedí, První hodnota je v prvním řádku, druhá hodnota je ve třetím řádku. Druhou chybou je že proměnná maximum žádná není, stačí Ti pracovat s hodnotami které jsou už uloženy v poli. Třetí chybou je že podmínka je nesmyslná. Je třeba si uvědomit s jakými hodnotami pracuješ a co je výsledek logických hodnot. Samotné pole(0,1) představuje hodnotu kterou ale s ničím neporovnáváš. Výsledek logického součinu je buď 0 nebo 1 a to porovnávat s nějakým maximem je nesmyslné.

Nahoru Odpovědět
6.6.2020 21:16
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 21:33

Dám Ti jednu otázku, zkus mi na ni co nejpřesněji odpovědět.

// test lokalniho maxima vnitrnich prvku
for (int i = 1; i < (SIZE - 2); i++) {
        if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i + 1])) {
                printf("%d[%d] ", nums[i], i);
        }
}

Otázka:
Zdůvodni, proč jsem ve výše uvedeném úryvku kódu použil indexy 1 a SIZE-2 pro rozsah cyklu for.

Nahoru Odpovědět
6.6.2020 21:33
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 21:41

Kvuli druhemu az předposlednímu prvku?

Editováno 6.6.2020 21:42
 
Nahoru Odpovědět
6.6.2020 21:41
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 22:08

Indexy s čísly 1 a SIZE-2 představují druhý a předposlední prvek, to ano. Ale proč jsem zvolil právě tyto hodnoty, proč ne třeba 0 a SIZE-1? Chci znát důvod. Respektivě dva které spolu úzce souvisí.

Nahoru Odpovědět
6.6.2020 22:08
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 22:15

Protože první a poslední prvek jsi vypsal zvlast? Ja vazne netusim, nechtej po me teorii, kterou bych si strasne rad precetl, ted koukam do skrypt, na vicerozmerna pole a nejsem o nic moudrejsi, co to jsou vicerozmerna pole, jak je setřídit, vic jsem z toho nevycetl, cili pokud Te ma odpověď neuspokoji, tak je mi lito.

 
Nahoru Odpovědět
6.6.2020 22:15
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 22:35

Smyslem mé otázky není to že po tobě chci teorii, ta s ní ani nesouvisí, ale získání tvého logického uvážení a pochopení toho jak daný úsek programu funguje. Tím se naučíš snáze řešit problémy a budeš-li toto trénovat, pak i schopnost utvářet programy přímo v hlavě. Když teď napíši odpověď, bude Ti to jasné.

Očekával jsem následující odpověď:

Důvodem, proč byly pro for cyklus použity rozsahy 1 a SIZE-2 (tedy druhý a předposlední prvek) bylo to, že algoritmus uvnitř for pracuje s hodnotami na sousedních indexech (zleva a zprava). Pro první prvek neexistuje žádný soused zleva, pro poslední prvek neexistuje žádný prvek zprava. Výraz podmínky pro použitý index i-1 pro první prvek by vedl k chybě programu z důvodu neplatného rozsahu, stejně tak výraz podmínky pro použitý index i+1 pro poslední prvek by vedl k chybě programu z důvodu neplatného rozsahu. Nelze pracovat s indexy o hodnotách -1 a 20. Proto byly indexy pro cyklus for stanoveny na hodnoty 1 a SIZE-2 aby se dalo pracovat se sousedy všech prvků pokrývající rozsah cyklu for.

Algoritmus pro určení zda lokální maximum leží i na prvním a posledním prvku pole je jiný od vnitřních prvků. Proto bylo zjištění lokálního maxima pro první a poslední prvek odděleno. Aby bylo zachováno logické pořadí lokálních maxim, byl algoritmus pro určení lokálního maxima uveden před algoritmem zjistění lokálního maxima vnitřních prvků a jako poslední byl uveden algoritmus zjišťování maxima pro poslední prvek. Tím je zaručena souslednost lokálních maxim všech prvků pole.

Nahoru Odpovědět
6.6.2020 22:35
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:6.6.2020 22:52

Postupuj systematicky. S 2D polem se pracuje obdobně jako s 1D polem. Je tam akorát navíc jeden rozměr. To hlavní co musíš je pochopit, kdy a za jakých podmínek použít 2D pole. To si můžeš představit jako plochu něčeho (třeba stránka knihy, kde první index udává řádek a druhý index pozici znaku na řádce). Dále třeba využiješ 2D pole když si budeš chtít uchovat teplotu každého dne v roce. Znovu připomínám, důležité je se naučit proč zrovna použít 2D pole. 2D pole se v programování používají velmi často, jejich znalost je pro úspěšné programování bezpodmínečná. Důležité je si pomatovat, že první index udává počet řádků, druhý index počet sloupců. Začni tím že se naučíš jak deklarovat 2D pole, jak inicializovat 2D pole, jak přistupovat k danému prvku pole, jak přečíst hodnotu na konkrétní pozici, jak uložit hodnotu na konkrétní pozici. Jak načíst uživatelská data na konkrétní pozici, jak vypsat celé 2D pole, jak přečíst konkrétní řádek, jak přečíst konkrétní sloupec, jak vypsat hodnotu na konkrétní pozici a další. Naučíš-li se tyto elementární části, nebude Ti 2D pole činit sebemenší problém.

Nahoru Odpovědět
6.6.2020 22:52
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na DarkCoder
Ondrej Zadrapa:6.6.2020 23:42
Sub Main()
        Dim pole(3, 3) As Integer, rnd As New Random
        For i = 0 To 3
            For j = 0 To 3
                pole(i, j) = rnd.Next(100)
            Next
        Next
        For i = 0 To pole.GetLength(0) - 1
            For j = 0 To pole.GetLength(1) - 1
                Console.Write("{0}({1},{2})", pole(i, j), i, j)
            Next
            Console.WriteLine()
        Next
        Console.WriteLine()
        If pole(0, 0) > pole(0, 1) Then
            Console.WriteLine("Lokalni maximum {0} na pozici({1},{2})", pole(0, 0), 0, 0)
        End If
        For i = 1 To pole.GetLength(0) - 2
            For j = 1 To pole.GetLength(1) - 2
                If pole(i, j) > pole(i - 1, j - 1) And pole(i, j) > pole(i + 1, j + 1) Then
                    Console.WriteLine("Lokalni maximum {0} na pozici({1},{2})", pole(i, j), i, j)
                End If
            Next
        Next
        If pole.GetLength(0) - 1 And pole.GetLength(1) - 1 > pole.GetLength(0) - 2 And pole.GetLength(1) - 2 Then
            Console.WriteLine("Lokalni maximum {0} na pozici({1},{2})", pole.GetLength(0) - 1 And pole.GetLength(1) - 1, pole.GetLength(0) - 1, pole.GetLength(1) - 1)
        End If
        Console.ReadKey()
    End Sub

Nez na to něco reknes, tak jsem zkusil nejprve vytvořit stejny program s 1D polem a když jsem zjistil, ze funguje bezchybne, tak jsem se pokusil opravdu jenom postupne nejprve vnorit jeden cyklus navíc, zmenil jsem počet promennych tak, aby si to sedelo a vyzkousel jsem to tak, jak jsem zatím pochopil, ze to ma fungovat. Jelikoz každý cyklus vraci dimenzi 0 a 1, radek a sloupec, tak jsem to takhle zkusil vytvořit, no nevypada to, ze by to fungovalo jak by mělo, uz me to alespoň neposila do pryc, ze mam index mimo pole. Navíc ucit se něco o pul noci není moc dobry napad. Ale uz jsem alespoň vykrocil spravnym smerem?

Editováno 6.6.2020 23:44
 
Nahoru Odpovědět
6.6.2020 23:42
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:7.6.2020 0:35

Jdeš správným směrem, je tam několik chyb ale nic co by se nedalo vyřešit. To hlavní co by Ti mohlo pomoci je to že je tu stále rozdíl mezi 1D pole a 2D polem v oblasti ohraničení. Když se podíváš na 1D pole, je to pás jehož krajní hodnoty jsou první a poslední prvek (pole[0] a pole[19] pro pole o velikosti 20). Y hlediska vizuální podoby 2D pole jsou krajní hodnoty všechny v prvním sloupci a posledním sloupci a všechny hodnoty v prvním a posledním řádku. Je tedy třeba vědět z jakého pohledu chceš maxima určit.

Teď ke kódu. Deklaruj 2D pole o velikosti 3x3, naplňuješ ho náhodnými hodnotami a poté si ho pro kontrolu vypisuješ. Až sem to vypadá vše OK.

V další části určuješ zda prvek na pozici 0,0 je maximem v porovnání s prvkem na pozici 0,1. Pokud tedy porovnáváš hodnoty pouze v horizontálním rozměru, pak je to správné. Pro zachování způsobu určování maxima toto budu brát jako důležitý prvek.

V poslední části nejspíš chceš zjistit zda poslední prvek je maximem. Ta je chybně. Pracuješ zde pouze s velikostí pole nikoli s hodnotou. Dále jak jsem v úvodu zmínil, krajních hodnot pro 2D pole z vizuálního hlediska je více. Pokud to budu brát v horizontální rovině, pak jsou to všechny prvky v prvním sloupci a všechny prvky v posledním sloupci. V paměti je ale 2D pole uspořádáno jako 1D pole, po řádcích. Pokud ale chceš brát pouze první a poslední prvek jako hraničíčí, může to udělat. Jelikož máš pole 3x3, pak testuješ maximum pole[2,2]. Pokud chceš používat funkci pro výpočet velikosti pole, musí být výsledek této hodnoty vzat jako index pole.

Zda VB umožnuje vkládat výsledky funkcí jako index pole, netuším. Ale můžeš to zjistit. protože chceš určit zda maximum je i na posledním prvku, tedy pole[2,2], musíš ho porovnat s hodnotou na pozici pole[2,1].

Následující zápis by mohl představovat pozici posledního prvku:

pole(pole.GetLength(0) - 1, pole.GetLength(1) - 1)

a předposledního prvku:

pole(pole.GetLength(0) - 1, pole.GetLength(1) - 2)

Pokud to VB nevezme, pak si výrazy na indexových pozicích musíš předpočítat, uložit do proměnné a tu pak dosadit na pozici indexu.

Musíš stále pracovat s hodnotou na dané pozici:
Tedy vždy musíš používat formát pole[ROW, COL].

Teď k té nejkomplikovanější části. Obtížně se Ti bude určovat zbytek prvního a posledního řádku protože pracuješ se 2 indexy a první a poslední řádek je neúplný.

V úvodu jsem zmínil že způsob hledání maxima děláš ve vodorovné rovině. Pak ale nemůžeš použít jako index hodnoty j-1 a j+1.

Nelze použít stejný způsob hledání maxima pro 2D pole a 1D pole. Pro určení maxima u 2D pole je třeba provést přepočet indexů. Musíš vědět jak to přepočítat. Že např. prvek na pozici 1,0 v 2D poli 3x3 odpovídá 4 prvku pole[3] v 1D poli. Stále se bavíme že pracujeme v hledání maxima v horizontální rovině.

Jak vidíš, je to o dost komplikovanější nežli u 1D pole. Abys tohle zvládl, musíš se o 2D poli dozvědět více. Musíš umět porovnat 1D pole s 2D polem. Jak už jsem zmínil, v paměti je 2D pole uloženo po řádcích a vypadá jako 1D pole. Ale pro práci s konkrétními indexy musíš umět přepočítat indexy.

Nahoru Odpovědět
7.6.2020 0:35
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ondrej Zadrapa
DarkCoder:7.6.2020 1:27

Abys viděl, o kolik je to ve 2D komplikovanější oproti 1D poli, zde je ukázka hledání lokálního maxima ve 2D poli 4x5.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 4
#define COL 5

int main(void) {
        int nums[ROW][COL];

        srand((unsigned int)(time(NULL)));

        // naplneni 2D pole nahodnymi hodnotami v rozsahu 0-99
        for (int i = 0; i < ROW; i++) {
                for (int j = 0; j < COL; j++) {
                        nums[i][j] = rand() % 100;
                }
        }

        // kontrolni vypis 2D pole (hodnota a index)
        for (int i = 0; i < ROW; i++) {
                for (int j = 0; j < COL; j++) {
                        printf("%d[%d][%d] ", nums[i][j], i, j);
                }
                putchar('\n');
        }
        putchar('\n');

        // test lokalniho maxima prvniho prvku
        if (nums[0][0] >= nums[0][1]) {
                printf("%d[%d][%d] ", nums[0][0], 0, 0);
        }

        // test lokalniho maxima vnitrnich prvku
        for (int i = 1; i < (ROW * COL - 1); i++) {
                if ((nums[i / COL][i % COL] >= nums[(i - 1) / COL][(i - 1) % COL]) && (nums[i / COL][i % COL] >= nums[(i + 1) / COL][(i + 1) % COL])) {
                        printf("%d[%d][%d] ", nums[i / COL][i % COL], i / COL, i % COL);
                }
        }

        // test lokalniho maxima posledniho prvku
        if (nums[ROW - 1][COL - 1] >= nums[ROW - 1][COL - 2]) {
                printf("%d[%d][%d] ", nums[ROW - 1][COL - 1], ROW - 1, COL - 1);
        }

        return 0;
}

Výstup programu:

19[0][0] 70[0][1] 44[0][2] 54[0][3] 40[0][4]
83[1][0] 64[1][1] 40[1][2] 41[1][3] 66[1][4]
55[2][0] 35[2][1] 74[2][2] 68[2][3] 25[2][4]
76[3][0] 38[3][1] 71[3][2] 63[3][3] 65[3][4]

70[0][1] 54[0][3] 83[1][0] 66[1][4] 74[2][2] 76[3][0] 71[3][2] 65[3][4]

Jak je vidět, určení maxima prvního a posledního prvku je přímočaré. Pro určení maxima vnitřních prvků už je třeba přepočtu z 1D do 2D pro správnou indexaci.

Práce s 2D poli může být zábavná.. :-)

Nahoru Odpovědět
7.6.2020 1:27
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 35 zpráv z 35.