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
Petr Vít
Člen
Avatar
Petr Vít:20.3.2018 21:20

Ahoj,

obracím se na Vás, jako na zkušené programátorské hlavy, aby jste mi pomohli s logickým návrhem.

Mám pole čísel. 10,9,8,7,6,5,­4,3,2,1,0,1,2,3,4,5,6,7,­6,5,4,3,2. v Grafickém vyjádření to bude tedy podobně jako písmena "Vi". Já bych rád zjistil dvě největší maxima a minima z pole, ale chronologicky za sebou.

To znamená že první maximum je číslo 10, první minimum je číslo 0, druhé maximum je číslo 7 a druhé minimum je číslo 2. Absolutně nevím jak to zapsat do kódu.

Díky předem za nápady

Editováno 20.3.2018 21:20
 
Odpovědět
20.3.2018 21:20
Avatar
Petr Šťastný
Tvůrce
Avatar
Odpovídá na Petr Vít
Petr Šťastný:20.3.2018 22:01

V tomhle případě bych asi udělal pomocné pole čísel, kam bych ukládal minima a maxima - tady by vypadalo nějak takhle:

{ 10, 0, 7, 2}

Výhodu to má, že s tím můžeš dál pracovat a snadno můžeš kód upravit, kdybys ty maxima nepotřeboval 2, ale třeba 2000.

Jestli potřebuješ rozlišit, co je maximum a minimum, tak to zase uděláš druhým pomocným polem, a to s hodnotami typu bool.

Možná by ale nebylo od věci slít všechno do jednoho pole a udělat si z dvojice int:bool (hodnota:max/min) strukturu (struct) a tu ukládat do jednoho pomocného pole. Určitě by to šlo více způsoby.

Editováno 20.3.2018 22:01
 
Nahoru Odpovědět
20.3.2018 22:01
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Petr Vít
DarkCoder:20.3.2018 23:19

Vytvoříš dynamicky alokované jednorozměrné pole celých čísel, do kterého budeš postupně ukládat společně minima a maxima ze zadaného pole. Porovnáváním sousedních prvků zadaného pole zjišťuješ, zda-li je průběh rostoucí čí klesající. Postupným porovnáváním sousedních prvků zjišťuješ udržení rostoucí nebo klesající tendence. Pokud se tendence mění, zapisuješ hodnotu do dynamicky alokovaného pole. Toto pole dle potřeby zvětšuješ. Pokud pole obsahuje jeden prvek (ten první), pak výsledkem je konstantní průběh. Pokud pole obsahuje více než jeden prvek, pak porovnáním prvního a druhého prvku zjišťuješ, zda-li je jako první průběh rostoucí nebo klesající. Na základě tohoto určíš, zda-li prvním prvkem je minimum nebo maximum. Z důvodu střídající tendence postačí vytvoření pouze jednoho výše uvedeného dynamicky alokovaného pole.

Nahoru Odpovědět
20.3.2018 23:19
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Petr Vít
Michael Škrášek:21.3.2018 0:33

Já bych to udělal nějak takhle:

static void Main(string[] args)
{
    int[] array = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2 };
    split(array.ToList(), Array.IndexOf(array, array.Max()), true, 4);
    Console.ReadKey();
}

static void split(List<int> array, int index, bool max_min, int count)
{
    if (count > 0)
    {
        Console.WriteLine(array.toString());
        Console.WriteLine($"{(max_min ? "Maximum" : "Minimum")}: {array[index]}");
        array.RemoveRange(0, index + 1);
        if (array.Count > 0)
            split(array, array.IndexOf(!max_min ? array.Max() : array.Min()), !max_min, count - 1);
    }
}

Pokaždé zjistim index MAX/MIN v poli a vše co je před indexem, už nepotřebuju ... smažu

Editováno 21.3.2018 0:35
Nahoru Odpovědět
21.3.2018 0:33
"I choose a lazy person to do a hard job. Because that person will find an easy way to do it. " Bill Gates
Avatar
zelvicek
Člen
Avatar
Odpovídá na Petr Vít
zelvicek:21.3.2018 6:55

Dobrosrdeční lidé ti už tady dali rady či kusy kódu. Já ti neporadím přímo, ale dokázal bys ty lokální špičky (minima a maxima) najít ty sám (jako člověk)? Pokud ano, máš algoritmus, který si jen potřebuješ nakreslit na papír (pro uvědomění si) a pak už jen převést do příslušného programovacího jazyku.
Hint: když ty špičky hledáš ty osobně, jaké informace si musíš poznačit (ať už v paměti nebo na papír)?

 
Nahoru Odpovědět
21.3.2018 6:55
Avatar
Petr Vít
Člen
Avatar
Petr Vít:21.3.2018 11:33

Těší mě že jsem předal dobře myšlenku a všichni chápete co mám na mysli. Avšak jsem tak trochu začátečník takže pokud by se tady našel někdo kdo by mi svoji ideu vysvětlil víc polopaticky.

Kód od Michala funguje ovšem pouze na tento zadaný příklad. Od Petra se mi líbí ta myšlenka škálovatelnosti, protože přesně to bych v budoucnu potřeboval. Jak poznávám "špičky"? Tak ze ty čísla převedu do grafu.

Měl bych uvést jak to přesně je. Reálně je to pole typu double o velikosti cca 200 hodnot.
A hodnoty se střídají. tzn že nemusí jít chronologicky za sebou. V mém příkladě to může vypadat takto.
10,9,8,7, 7.5,7,8, 6,5,4,3,2,1,,1,2,3,4,5,6,7,6,5,4,3,2.

Potřebuji zjistit větší max a min tzn. aby kód ignoroval nějaké menší odchylky.

Mě napadlo že využiji samotné číslo indexu. Tzn pokud číslo 10 je v indexu na místě 25, tak od 25 místa hledej minimum. Až najde minimum tak od této hodnoty hledej maximum atd...

 
Nahoru Odpovědět
21.3.2018 11:33
Avatar
zelvicek
Člen
Avatar
Odpovídá na Petr Vít
zelvicek:21.3.2018 14:08

A co takový "trend funkce"? Sprostý výraz? Vážně není!
Uvědom si, co ty sám provádíš, když "skenuješ" sekvenci a ty špičky hledáš. Najdeš trend funkce a bod jeho změny prohlásíš za lokální maximum (tedy pokud budeme ignorovat "záchvěvy").
Trošku lidštěji:
0tý index: z jednoho bodu trend nepoznáš - jsi v pytli a musíš si zapamatovat fakt, že trend zatím neznáš.
1ní index: už máš dvě hodnoty a z nich už dokáš určit trend (klesající/stou­pající). Paráda.
2hý index: splňuje prvek trend? Ano->pokračuješ ve skenu. Ne->Předchozí prvek prohlásíš za lokální maximum, poznačíš si opačný trend, pokračuješ ve skenu.

No není to easy?
Pokud chceš zapracovat ignoraci zákmitů, musíš si určit jeho max velikost a zvětšit peek scan (česky asi dopředný scan). Taky by se hodila znalost rekurze (i když to jde I bez ní). Krásně ji použil Michael.

 
Nahoru Odpovědět
21.3.2018 14:08
Avatar
Milan Suchomel:21.3.2018 22:56

Co třeba něco takového? Procházíš pole a kontroluješ aktuální prvek s předchozím a následujícím s tím, že první a poslední prvek přidáš automaticky do výsledného listu.

static void Main(string[] args)
{
    double[] array={ 10, 9, 8, 7, 7.5, 7, 8, 6, 5, 4, 3, 2, 1,0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2};
    List<double> extrems = new List<double>();

    for (int i = 0; i < array.Length; i++)
        if (i == 0 || i == array.Length - 1) extrems.Add(array[i]);
        else if ((array[i + 1] > array[i] && array[i - 1] > array[i]) || (array[i + 1] < array[i] && array[i - 1] < array[i]))
            extrems.Add(array[i]);

    Console.WriteLine(string.Join(", ", extrems));
}

Výpis:

10, 7, 7,5, 7, 8, 0, 7, 2
 
Nahoru Odpovědět
21.3.2018 22:56
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 8 zpráv z 8.