Matematické Fórum

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

#1 15. 07. 2011 12:14

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Algoritmus k vypsání všech variací

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

  • (téma jako nevyřešené označil(a) sifik)

#2 15. 07. 2011 20:12

check_drummer
Příspěvky: 5511
Reputace:   106 
 

Re: Algoritmus k vypsání všech variací

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á.


"Máte úhel beta." "No to nemám."

Offline

 

#3 16. 07. 2011 08:49

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#4 16. 07. 2011 09:27

LukasM
Příspěvky: 3274
Reputace:   193 
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#5 16. 07. 2011 18:27

check_drummer
Příspěvky: 5511
Reputace:   106 
 

Re: Algoritmus k vypsání všech variací

↑ sifik:
Rekurzivní funkce generuje čísla přesně v tom pořadí, jaká je jejich "hodnota", tj. 00000,00001,00002,...atd.


"Máte úhel beta." "No to nemám."

Offline

 

#6 16. 07. 2011 19:39

Oxyd
Příspěvky: 614
Škola: MFF UK, teoretická informatika
Pozice: Student
Reputace:   31 
 

Re: Algoritmus k vypsání všech variací

Algoritmus existuje. Protože velikost výsledku je exponenciální ($n^k$, 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?


Mýlím se častěji, než bych chtěl. Pokud vám v mém příspěvku něco nehraje, neváhejte se zeptat.
Jsem stále mlád a je mi příjemnější tykání. :)

Offline

 

#7 16. 07. 2011 20:14

check_drummer
Příspěvky: 5511
Reputace:   106 
 

Re: Algoritmus k vypsání všech variací

↑ Oxyd:
Stačí se např. podívat na tachometry "starších" aut.


"Máte úhel beta." "No to nemám."

Offline

 

#8 16. 07. 2011 20:36

Oxyd
Příspěvky: 614
Škola: MFF UK, teoretická informatika
Pozice: Student
Reputace:   31 
 

Re: Algoritmus k vypsání všech variací

↑ check_drummer:

No jasně. :) Že mě to hned nenapadlo.

A už jsem našel i hezké video takového počítadla.


Mýlím se častěji, než bych chtěl. Pokud vám v mém příspěvku něco nehraje, neváhejte se zeptat.
Jsem stále mlád a je mi příjemnější tykání. :)

Offline

 

#9 16. 07. 2011 20:56

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#10 16. 07. 2011 21:12

Oxyd
Příspěvky: 614
Škola: MFF UK, teoretická informatika
Pozice: Student
Reputace:   31 
 

Re: Algoritmus k vypsání všech variací

↑ sifik:

Ano, je to správná metoda. A řekl bych, že moc jiných se vymyslet nedá -- kromě rekurzivní variace na stejné téma.


Mýlím se častěji, než bych chtěl. Pokud vám v mém příspěvku něco nehraje, neváhejte se zeptat.
Jsem stále mlád a je mi příjemnější tykání. :)

Offline

 

#11 20. 07. 2011 11:35

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Re: Algoritmus k vypsání všech variací

↑ Oxyd:

Dobrá a jak by se to potom udělalo, kdybych výčet kombinací chtěl doplnit i o písmena? Asi také zase přes rekurzi, ale vůbec mě nenapadá, jak by pak mělo vypadat tělo funkce?

Offline

 

#12 20. 07. 2011 12:55

pietro
Příspěvky: 4792
Reputace:   187 
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#13 20. 07. 2011 18:07

check_drummer
Příspěvky: 5511
Reputace:   106 
 

Re: Algoritmus k vypsání všech variací

↑ 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.


"Máte úhel beta." "No to nemám."

Offline

 

#14 20. 07. 2011 20:02

pietro
Příspěvky: 4792
Reputace:   187 
 

Re: Algoritmus k vypsání všech variací

↑ check_drummer: Dík, rozumiem....... naštudujem ...rekurziu... (tachometer s variabilným počtom pozícií)

Offline

 

#15 20. 07. 2011 20:18

petrkovar
Veterán
Místo: Ostrava/Krmelín
Příspěvky: 1012
Pozice: VŠB - TU Ostrava
Reputace:   23 
Web
 

Re: Algoritmus k vypsání všech variací

Na 14. slajdu z přednášek nebo na straně 39 ve skriptech najdete mazaný způsob, jak implementovat generování všech variací, aniž by bylo potřeba "dynamizovat" počet vnořených cyklů. Pochopení však vyžaduje důkladně si uvedenou proceduru promyslet.

Offline

 

#16 08. 08. 2011 18:25

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Re: Algoritmus k vypsání všech variací

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

 

#17 09. 08. 2011 09:08

pietro
Příspěvky: 4792
Reputace:   187 
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#18 09. 08. 2011 11:22

petrkovar
Veterán
Místo: Ostrava/Krmelín
Příspěvky: 1012
Pozice: VŠB - TU Ostrava
Reputace:   23 
Web
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

#19 15. 08. 2011 19:17

sifik
Zelenáč
Příspěvky: 6
Reputace:   
 

Re: Algoritmus k vypsání všech variací

↑ 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

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson