[PASCAL] Wszystkie kombinacje liczb

0

Witam!

Potrzebuje aplikacji w PASCALU gdzie...

zakładając że mam tablice w której są odpowiednio w indeksach liczby 1,2,3,4,5,6,

potrzebuje programu który będzie mi robił wszystkie kombinacje tych liczb, czyli np.

  1. kombinacja 1,2,3,4,5,6
  2. kombinacja 1,3,2,4,5,6
  3. kombinacja 1,5,2,3,6,4
    ...

Liczby nie mogą się powtarzać wśród tych liczb.

Myślałem o pętlach, i było by to dobre wyjście, ale jest mały problem... ja nie wiem ile będzie tych liczb, czyli może być tak że 6, a może być i 4, albo 10 :) i tu jest problem w pascalu aby nie powtarzały się,

Znalazłem na początek coś takiego:

program Permutacje;
uses crt;
var n,k,dl_slowa,il_permut,spr,poz,i,max:longInt;
    slowo_wyj,slowo_0,slowo,slowo_st:string;
    x:char;
    t:array[1..255] of integer;
    key:char;
const slowo_max:string='abcdefghijklmnoprstuvwxyz';
procedure sprawdz_i_wstaw(x:char;nr:integer);
begin
  for k:=poz to dl_slowa do
  if (slowo_st[k]=x) and (t[ord(x)]=0)
     then begin
            slowo[nr]:=x; spr:=1;
            t[ord(x)]:=1;
          end;
end;
begin
  clrScr;
  slowo_0:='AABEGLR';
  dl_slowa:=length(slowo_0);
  slowo:=copy(slowo_max,1,dl_slowa);
  slowo_st:=slowo;
  il_permut:=1;
  writeLn(il_permut,'. ',slowo_0);
  max:=1; for n:=1 to dl_slowa do max:=max*n;
  repeat
    for n:=1 to 255 do t[n]:=0;
    n:=1;
    while slowo[dl_slowa-n]>slowo[dl_slowa-n+1] do n:=n+1;
    poz:=dl_slowa-n;
    i:=0;
    spr:=0;
    repeat
      x:=char(ord(slowo[poz])+1+i);
      sprawdz_i_wstaw(x,poz);
      i:=i+1;
    until spr=1;
    x:='!';
    for n:=1 to dl_slowa-poz do
    begin
      i:=0;
      spr:=0;
      repeat
        x:=char(ord(x)+1);
        sprawdz_i_wstaw(x,poz+n);
        i:=i+1;
      until spr=1;
    end;
    il_permut:=il_permut+1;
    slowo_wyj:='';
    for i:=1 to dl_slowa do slowo_wyj:=slowo_wyj+slowo_0[ord(slowo[i])-96];
    writeLn(il_permut,'. ',slowo_wyj);
    slowo_st:=slowo;
{    key:=readKey;}
  until (slowo_wyj='ALGEBRA') or (il_permut=max);
  readLn;
end. 

ale raczej nie za wiele się da z tego wyciągnąć.

Chciałbym aby wewnątrz pętli mieć swobodny dostęp za każdym razem do danych liczb, czyli abym mógł na nich operować w danym cyklu,

wygodnie by było gdyby była tablica dynamiczna, i miała tyle elementów ile akurat teraz będzie przetwarzanych, a ja będę miał dostęp wewnątrz pętli do "akurat" tak ułożonego schematu liczbowego :)

0
modrih napisał(a)

potrzebuje programu który będzie mi robił wszystkie kombinacje tych liczb, czyli np.

  1. kombinacja 1,2,3,4,5,6
  2. kombinacja 1,3,2,4,5,6
  3. kombinacja 1,5,2,3,6,4
    ...

moim zdaniem zle do tego podchodzisz.... tzn, nie wiem ale ja od razu zaczynam myslec w ten sposob:
wyobraz sobie ze najmniejsza mozliwa cyfra bedzie 0 a najwieksza 9... jak wtedy najprosciej utworzyc wszystkie mozliwe kombinacje, bez powtorzen?
a no np tak:

for i:=0 to 99 do
  writeln(i);

gdybys dodal poprzedzajace zera dostalbys:

00
01
02
03
...
08
09
10 //tu przelom.
11
12
13
...
19
20 //znow przelom
21
22
itd...

czyli w momencie gdy ostatnia cyfra liczby osiagnie maksymalna wartosc to zmieniasz ja na minimalna, a cyfre poprzednia zwiekszasz o 1. proste.

w przypadku gdy mozesz uzyc tylko okreslonych liczb juz sie sprawa troche komplikuje. ale zasada sie nie zmienia:
robisz tablice intow. moze byc dynamiczna ale na poczatek proponuje dac "zwykla" i jak caly kod bedzie dzialal to wtedy przerobisz na dynamiczna - unikniesz wielu bledow trudnych do zlokalizowania (ciezko dojsc czy blad zwiazany z tablica dynamiczna czy z samym "liczeniem").
potem dajesz dwie zmienne, np min i max: beda oznaczaly najwieksza i najmniejsza cyfre jakiej mozna uzyc w kombinacji. w Twoim przypadku 1 i 6.
na dziendobry wypelniasz wszystkie komorki tablicy tab ta sama wartoscia=min.
potem glowna petla (repeat..until):

   writeln(liczba_zlozona_z_cyfr_z_tablicy); //tak jakbys ustawil obok siebie wszystkie cyfry siedzace w tablicy.
   inc(tab[dlugosc_tablicy -1]); //czyli dodajesz 1, nie wiem czy ta sie to zrobinc uzyajac inc() ale tak jest bardziej czytelnie.
   for i:=dlugosc_tablicy-1 downto 1 do //(1, nie 0!)
        if tab[i]>max then
          begin
            tab[i]:=min;
            inc(tab[i-1]);
          end;

glowna petle wykonujesz do momentu, gdy wszystkie cyfry w Tab[] beda rowne max, lub (to zeby w razie bledu uniknac petli nieskonczonej) do momentu gdy tab[0]>max.
mysle ze niczego nie pominalem, nic nie pomieszalem i ze napisalem w miare zrozumiale ;]
powodzenia

0

Dziękuje serdecznie za pomoc :) , chciałem jeszcze nadmienić że będą tutaj też liczby typu od 1 do 105 ;) i będę musiał ułożyć podwójnie wszystkie kombinacje od 1,2,3...105, np. 1 i 2 , albo 1 i 105, albo 3 i 32, albo 2 i 52, i tak dalej :) ale to na to samo chyba wyjdzie jak będę miał poukładane koło siebie - np. 1, 105, 23 , 34, 54 ... (do 105).

wiem że tego jest pierońsko dużo, ale może Pascal da radę.

Przeanalizuje, bo coś mi już troszkę troszkę świta po pomocy wyżej.

0

teraz widze ze chyba niepotrzebnie ta petla for sie wykonuje za kazdym razem.
mozna dac przed nia warunek:

if tab[dlugosc_tablicy-1]=max then ...

zawsze troche szybciej, szczegolnie przy dlugich tablicach.
btw: mozesz tu wkleic kod jak skonczysz? przyda sie dla przyszlych pokolen :)

0

W porządku, ale jest jeszcze jeden problem, żadna z liczb nie może się powtarzać, czyli nie mogę mieć np. 1,45,32,24,1...

jeżeli mam od 1 do 45 , to będzie 45 cyfr :) (oczywiście tak dużych nie przewiduje, podaje jako przykład).

Bardziej realny przykład liczby od 1 do 12.

więc mamy np taki układ:

1,4,2,3,5,6,7,8,9,10,11,12

12 cyfr, które się nie powtarzają, a mi potrzeba wszystkie kombinacje jakie można ułożyć z tych 12 cyfr :), czyli jak pamięć mnie nie myli 12! - 1.

No nic powolutku kombinuje z Twoimi wskazówkami.

Wybacz, kiepsko tłumacze o tej godzinie :)

0

to po prostu n-elementowa kombinacja n-elementowego zbioru bez powtórzeń, rozwiązań jest multum w necie. poniżej wersja napisana w c# (nie mam delphi pod ręką) na szybko - na pewno można to zrobić lepiej, np. bez ciągłego sprawdzania w liście.
private void CombinationWithoutRepetition(int[] digits, List<int> set)
{
for (int i = 0; i < digits.Length; i++)
{
if (set.IndexOf(digits[i]) >= 0) continue;

	if (set.Count == digits.Length - 1)
	{
		for (int j = 0; j < set.Count; j++)
			Console.Write(set[j] + ", ");
		Console.WriteLine(digits[i]);
	}
	else
	{
		set.Add(digits[i]);
		CombinationWithoutRepetition(digits, set);
		set.RemoveAt(set.Count-1);
	}
}

}

...
CombinationWithoutRepetition(new int[] {1, 2, 3, 123}, new List<int>());

1 użytkowników online, w tym zalogowanych: 0, gości: 1