Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.
Nástěnka
❗22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
❗04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
❗23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.
Nejste přihlášen(a). Přihlásit
Dobrý den,
potřeboval bych poradit. Existuje nějaký alogismus, který vypíše všechny možnosti (variace) například u pětimístného hesla, které se například skládá pouze z čísel? Nemusí to být zrovna heslo... Jde mi jen o to, jak na to, když znám délku neznámého řetězce a z čeho se skládá... Pokud žádný rakový algoritmus neexistuje, jak tuto úlohu řešit?
Předem díky za radu.
Offline
Variacemi asi myslíš variace s opakováním, že?
Lze to, např. elegantně rekurzí - v každém rekurentním volání zvětšíš hodnotu na i-tém místě a zavoláš rekurzivní funkci pro i+1-ní místo.
Řekl jsem to stručně, možná i trochu nepřesně, ale myšlenka by mohla být jasná.
Offline
↑ check_drummer:
Nevím jestli jsem to dobře pochopil, ale pomocí tvého návrhu bych asi nepokryl všechny možnosti.
Protože dejme tomu že bych začal s rekurzivní funkcí na 00000 následně by bylo 10000, 11000, 11100, 11110, 11111, 21111 atd.... Jenže já potřebuji pokrýt i možnosti jako je 0100, 00100, 00010, 00001....
Třeba si to myslel správně a já to jen blbě pochopil, proto prosím o přiblížení problému.
Offline
↑ sifik:
No, jestli tomu dobře rozumím.. Jaké číslo bude následovat po 99999?
Jinak nápad na ilustraci jak to funguje - spusť si ve windows kalkulačku, dej tam +1, podrž si enter a sleduj vývoj jednotlivých míst. Tam se taky protočí všechny možnosti (před číslem si představ nuly). Lépe je to podle mého vidět v binární soustavě (kalkulačka do ní jde přepnout - je to ten přepínač Bin).
Offline
↑ sifik:
Rekurzivní funkce generuje čísla přesně v tom pořadí, jaká je jejich "hodnota", tj. 00000,00001,00002,...atd.
Offline
Algoritmus existuje. Protože velikost výsledku je exponenciální (
, kde n je počet možných znaků, k je délka hesla), tak i algoritmus má exponenciální složitost (a určitě neexistuje algoritmus s lepší složitostí, protože by nemohl ani stihnout vypsat tak velký výsledek).
Řekněme že znaky jsou jenom číslice (obecně si prostě zvolíš nějaké pořadí znaků, abys mohl jít "o jeden znak dál").
Začneš s posloupností 00...0. Pak zvětšuješ první člen, dokud ti nedojdou znaky: 10...0, 20...0, ..., 90...0. Pak ťukneš druhý člen o jedna nahoru, první resetuješ na 0 a pokračuješ: 01...0, 11...0, ..., 91...0. Pak zas ťukneš druhý člen, první resetuješ. Atd. Pokaždé, když ti v i-tém členu dojdou znaky, tak (i + 1)-ní pošoupneš o znak výš a resetuješ i-tý na 0.
Tenhle princip jsem už určitě viděl v některých hodinářských přístrojích (implementovaný mechanicky) -- tuší někdo, jak se tomu říká? Ještě lépe -- najde někdo animaci tohohle mechanismu?
Offline
↑ Oxyd:
Stačí se např. podívat na tachometry "starších" aut.
Offline
↑ check_drummer:
No jasně. :) Že mě to hned nenapadlo.
A už jsem našel i hezké video takového počítadla.
Offline
↑ check_drummer:
Ano, tachometry jsou přesným znázorněním problému...
Nicméně ve své podstatě je to hrozně jednoduché, ne?
Protože, řekněme že máme zase to pětimístné heslo a že se skládá pouze z čísel. Takže 10 na pátou nám dá 100,000 kombinací....
Výpis začíná na 00000 a pořád se dokonala o jedno zvětšuje: 00001, 00002... 15691, 15692 atd... a tato posloupnost se zastaví na čísle 99999 a když tomu přičtu nulu je o přesný počet kombinací.
Tato metoda (pokud se to dá vůbec tak nazvat) je správná ne? Protože, výsledná množina obsahuje, například, 00062 i 00026 i 62000 atd...
Offline
↑ sifik:
Ano, je to správná metoda. A řekl bych, že moc jiných se vymyslet nedá -- kromě rekurzivní variace na stejné téma.
Offline
↑ sifik: Ahoj, nech chceme variácie s opakovaním tretej triedy z prvkov označených znakmi 0,1,2,....9, 10=A, 11=B, 12=C, 13,14
Potom napr. v jazyku Basic to generuje
For a=0 to 14 step 1
For b=0 to 14 step 1
For c=0 to 14 step 1
print a,b,c
next c
next b
next a
ale sú aj online generátory variácií.
Offline
↑ pietro:
Problém by nastal, pokud by nebylo předem (rozuměj před psaním programu) dáno kolik členů má ta posloupnost mít. Pak bychom museli nějakým způsobem "dynamizovat" počet vnořených cyklů - např. s použitím již zmíněné rekurze.
Offline
↑ check_drummer: Dík, rozumiem....... naštudujem ...rekurziu... (tachometer s variabilným počtom pozícií)
Offline
Offline
Zkusil jsem tedy napsat program, na Procházení všech variací, jak je popsán na straně 39 ve skriptech. Kód vypadá následovně:
int i, j;
int[] select = { 1, 2, 3, 4 };
select[i = 0] = -1;
while (i >= 0)
{
if (++select[i] >= 100000) { i--; continue; }
for (j = 0; j < i; j++)
if (select[i] == select[j]) break;
if (j < i) continue;
if (++i < select.Length) { select[i] = -1; continue; }
Console.WriteLine(select[j]);
i--;
}
Console.ReadLine();
Tento skript vypíše všechny čísla od 1 do 100000, jak je nastaveno.
Jenže vůbec netuším k čemu tam je číselné pole select, protože ať dám to zmíněného pole jakýkoliv číslo, výstup je vždy stejný. (Pokud jsem dobře pochopil, že v tomto poli by měli být čísla, z kterých by se měli výsledné variace skládat? Protože jinak by šlo použít pouze pravidlo přičítání jendičky)
Další problém je, že smyčka while nikdy neskončí. Nebo-li jakmile se vypíše poslední variace (číslo 100 000) program začne vypisovat zase od začátku (od 1).
↑ pietro:
Povedlo se ti něco postavit pomocí rekurzí?
Offline
↑ sifik: Ani nie, voľajako som sa uspokojil ako konzument s týmto
http://users.telenet.be/vdmoortel/dirk/ … tions.html
http://www.mathsisfun.com/flash.php?pat … Calculator
ale v pozadí to mám uložené :-) dík.
Offline
↑ sifik:Pole select bude *vždy* obsahovat čísla 1..n. Můžeme jej však použít jako indexové pole pro jinou množinu, která může obsahovat libovolné prvky. Proto řádek " int[] select = { 1, 2, 3, 4 };" nemá očekávaný efekt.
Dále bylo chybou nahradit N číslem 10000. N je počet prvků, ne počet variací. Asi mělo být N=10, ale obecně N je tolik, kolik je prvků, ze kterých vybíráme. Proto cyklus neskončil....
Offline
↑ pietro:
Jako nouzovka to stačí, ale mě šlo spíše o pochopení problému, než o nalezení "ob-kliky". Navíc ta první webovka generuje hrozně pomalu, a ta druhá ta to ani nezkusí raději napíše "Your list is too long" nebo co jsem tam četl :D
↑ petrkovar:
Aha... nicméně pořád se mi nedaří použít pole select jako pole indexové pro jinou množinu:
char[] samohlasky = new char[] {'a', 'b', 'c', 'd'};
//Console.WriteLine(samohlasky[3]);
int i, j;
int[] select = new int[4];
int N = select.Count();
int K = select.Length;
select[i = 0] = -1;
while (i >= 0)
{
if (++select[i] >= N) { i--; continue; }
for (j = 0; j < i; j++)
if (select[i] == select[j]) break;
if (j < i) continue;
if (++i < K) { select[i] = -1; continue; }
Console.WriteLine(select[j]);
i--;
}
Console.ReadLine();
Připravil jsem pro to množinu samohlasky, kterou jsou prozatím naplnil 4 prvky, ale nedaří se mi je použít tak, jak byhc chtěl... zkoušel sjem to např. přes cyklus foreach:
foreach (int k in samohlasky)
{
//Console.WriteLine(k.ToString());
select[k] = samohlasky[k];
}
ale byl to pouze bohužel výstřel do prázdna.
Offline