Gerar números - um pouco confuso!

Delphi

10/11/2003

Bom dia a todos,
alguém teria disponível algum componente ou função para gerar números com uma ordem pré-estabelecida e armazená-los. Explicando melhor:
Vamos supor que os números dados sejam 1, 2 3, e 4. Ele faria a combinação desses números em terno, sem repetir nenhum valor, veja:
1 2 3
1 2 4
1 3 4
2 3 4

Depois jogaria num memo.

Alguém me dá uma luz?
Valeu!


Anarchybra

Anarchybra

Curtidas 0

Respostas

Marconi

Marconi

10/11/2003

O que voce pode fazer é simples:

Coloque em uma Matriz os números que deseja

var M:Array of Array of word;
i,j,k:word;
begin
setlenght(M,4) // uzando o seu exemplo
M[0]:=1;
M[1]:=2;
M[2]:=3;
m[3]:=4;
// lembrando que uma matriz de 4 elementos vai de 0 a 3.
// agora é só montar o loop
for i:=0 to 1 do begin
for j:= i+1 to 2 do begin
for k:=j+1 to 3 do begin
memo1.lines.add(IntToStr(M[i])+´ ´+IntToStr(M[j])+IntToStr(M[k]));
end;
end;
end;
M.release; // limpando M da memória
end;

Espero ter ajudado

Marconi


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Muito obrigado Marconi pela resposta marconi,
mas estou tendo problemas com o seu código.
Quando atribuo um valor a matriz ´M[0]:=1;´ e na conversão dentro do memo, ´IntToStr´.

Valeu!


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Já resolvi o problema Marconi, mas estou com uma outra dúvida?
Onde determino a quantidade de Números e a quantidade de combinações, por exemplo:
Parace óbvio mas não consegui.

Este exemplo mostra combinações de 1 até 4, em terno.
Como faço para alterar as combinações para de 1 até 10 em terno, pois quando mundo o números de elementos da matriz, ele também muda a combinação, sempre subtraindo 1 do números total de elementos.

Você poderia me ajudar?


GOSTEI 0
Marconi

Marconi

10/11/2003

Desculpe não responder imediatamente, mas só lí hoje.

Voce pode dimensionar a Matriz do tamanho que desejar.

Para 10 números será setlenght(M,10)
mais uma vez lembrando que o décimo elemento é M[9] e o primeiro é M[0]. Na tentativa de ler M[10] vai dar erro de endereçamento na memória.

Também não é necessário que os números que serão combinados sejam exatamente de 1 a 10. Pode-se atribuir valores diversos.

Ex. M[0]:=5;
M[1]:=17;
... e assim por diante. Eles serão combinados de três em três.

Para mudar o número de combinações para quadras, basta acrescentar uma letra no loop;

for n:=0 to lenght(M)-3 do begin
for i:=n+1 to lenght(M)-2 do begin
for j:= i+1 to lenght(M)-1 do begin
for k:=j+1 to lenght(M) do begin
memo1.lines.add(IntToStr(M[i])+´ ´+IntToStr(M[j])+IntToStr(M[k]));
end;
end;
end;
end;

No exemplo eu estou montando quadras e em vez de determinar o valor de M, e verifico o tamanho para determinar o loop.

Para deixar o número que se deseja arranjar (ternos, quadras, quinas, etc) como variáveis, fica um pouco mais complexo, mas também é possivel.

Marconi


GOSTEI 0
Marconi

Marconi

10/11/2003

:oops:

Correção

No exemplo anterior mude as linhas abaixo

for n:=0 to lenght(M)-4 do begin
for i:=n+1 to lenght(M)-3 do begin
for j:= i+1 to lenght(M)-2 do begin
for k:=j+1 to lenght(M)-1 do begin

senão vai dar erro.

Marconi


GOSTEI 0
Marconi

Marconi

10/11/2003

Completando

Para que o número de elementos a ser combinados possa também ser escolhido durante a execução do programa, voce precisará de outra matriz para controlar os ´loops´.

Em vez de declarar as variáveis n,i,j,k, etc. pode-se declarar uma Matriz variaveis inteiras, para controlar os loops e para que possa ser dimensionada em tempo de execução.

Marconi


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Marconi, gostaria de agradecer sua atenção e te pedir um último favor.
Meu programa, funciona basicamente assim:
O usuário entre com a quantidade de números que ele quer fazer a combinação. Sempre em sequência e em ordem crescente e eu faço as combinações para ele.
Por enquanto, com as dicas que me deu, a quantidade de números é automática [b:56fb0486c5]´SETLENGTH(M,25);´[/b:56fb0486c5]
Como faria para esta quantidade de número ser manual, onde o usuário entraria com o números e o programa realizaria todo o processo?

Muito obrigado novamente!


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Eu cheguei a esta procedure....

procedure tform1.duque;
var M:Array of integer;
a1, a2, n, contM, cont:integer;
begin
listbox1.items.clear;
n:=StrToInt(edit1.text);
setlength(M,n);
for contM:=0 to n do begin
for cont:=contM+1 to n-1 do begin
M[contM]:=cont;
end;
end;

for a1:=0 to length(M)-2 do begin
for a2:=a1+1 to length(M)-1 do begin
listbox1.items.add(IntToStr(M[a1])+´-´+IntToStr(M[a2]));
end;
end;

Ele faz a quantidade certa de jogos, mas não gira o contador!


GOSTEI 0
Marconi

Marconi

10/11/2003

No código que voce passou, eu não entendi o que se pretende com este trecho

for contM:=0 to n do begin
for cont:=contM+1 to n-1 do begin
M[contM]:=cont;
end;
end;

pode-se perfeitamente preencher a matriz com
[b:7f664c145d]for contM:=1 to n do begin
M[contM-1]:=contM;
end;[/b:7f664c145d]

Se bem que o segredo é preenche-la com outros números, que mesmo em ordem crescente não necessitam ser sequenciais.

Marconi


GOSTEI 0
Marconi

Marconi

10/11/2003

Me esclareça o que voce pretente realmente.

Combinar [b:b75ad5cf50] n números 2 a 2 [/b:b75ad5cf50]
Combinar [b:b75ad5cf50] n números com quantidades variáveis[/b:b75ad5cf50]

Seria para Loterias, então teríamos um máximo de 10.

Marconi


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Amigo Marconi, muito obrigado pela atenção!
No meu caso não seria para loteria (apesar da coincidência), seria para rotinas de bingo!
Agora respondendo a sua pergunta, eu queria fazer combinações de N elementos e N variáveis. Seria arbitrario, o usuário escolheria um limite de números, 50 por exemplo e a combinação, por exemplo, combinar em terno.

Agradeço novamente sua atenção, estou chegando lá!


GOSTEI 0
E_gama

E_gama

10/11/2003

Talvez essa não seja a solução definitiva, mas já deve dar uma luz...

Para testar a rotina abaixo, coloque no form dois TMemo´s, um TEdit e um TButton, e escreva as rotinas abaixo.

No [b:2a5ac171bd]Memo1[/b:2a5ac171bd], preencha cada linha com um numero que vc quer combinar, e no [b:2a5ac171bd]Edit1[/b:2a5ac171bd] digite a quantidade de agrupamentos (no seu exemplo, é 3 - ´terno´). Quando vc clicar no [b:2a5ac171bd]Button1[/b:2a5ac171bd], o [b:2a5ac171bd]Memo2[/b:2a5ac171bd] será preenchido com os combinações geradas...

Devido a forma com foi feito, não terá uma boa performance, mas acreditando que vc não irá utilizar uma quantidade muito grande de números, então isso não será problema.

Espero que lhe ajude...

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Edit1: TEdit;
    Memo2: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure GeraNumeros(Vetor: TStrings; NumAgrupamentos: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.GeraNumeros(Vetor: TStrings; NumAgrupamentos: Integer);
var AuxLista: TStrings;
    S       : string;
    I       : Integer;

begin
  AuxLista := TStringList.Create;
  while Vetor.Count >= NumAgrupamentos do
    begin
      AuxLista.Text := Vetor.Text;
      while AuxLista.Count >= NumAgrupamentos do
        begin
          S := ´´;
          for I := 0 to (NumAgrupamentos - 1) do
            S := S + AuxLista.Strings[I] + ´-´;
          Memo2.Lines.Add(S);
          AuxLista.Delete(NumAgrupamentos - 1);
        end;
      Vetor.Delete(NumAgrupamentos - 2);
    end;

  AuxLista.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Vetor1, Vetor2 : TStrings;
    NumAgrupamentos: Integer;
begin
  Memo2.Lines.Clear;
  Vetor1          := TStringList.Create;
  Vetor2          := TStringList.Create;
  Vetor1.Text     := Memo1.Lines.Text;
  Vetor2.Text     := Memo1.Lines.Text;
  NumAgrupamentos := StrToInt(Edit1.Text);

  while Vetor1.Count >= NumAgrupamentos do
    begin
      GeraNumeros(Vetor1, NumAgrupamentos);
      Vetor2.Delete(0);
      Vetor1.Text := Vetor2.Text;
    end;
end;

end.




GOSTEI 0
E_gama

E_gama

10/11/2003

Desculpe-me mas tem um bug na rotina que passei anteriormente.
Vou verificar de pois repasso a rotina correta.


GOSTEI 0
Rafael Heise

Rafael Heise

10/11/2003

Você está querendo dizer um determinado número de números e quer que a função gere pra você todas as possíveis combinações sem repetir certo?????
Então, você precisa usar um array de tamanho indefinido para guardar os números, digamos que você queira começar com 1 e terminar com 4 (1,2,3,4) ou que você queira que gera apenas com os números 1,3,5,7. Então você precisa primeiro guardar esses números. Depois você precisa fazer uma função recursiva para gerar os possíveis números.
Faça o seguinte:
Primeiro, declare uma variável do tipo TStringList no private da sua unit.
Digamos Lista: TStringList;
então você faz
procedure TForm1.FormCreate(Sender: TObject);
begin
  Lista := TStringList.Create;
end;

e mais isso:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Lista.Free;
end;


Agora você já tem disponível um array infinito...
agora, você coloca um TSpinEdit, e dois botões, com captions Limpar e Adicionar, e um Edit com a propriedade ReadyOnly setada para True. Não esqueça de limpara a propriedade Text do edit. Dai faça então o seguinte:

botão limpar:
TForm1.bbClear(Sender: TObject);
begin
  Lista.Clear;
  Edit1.Clear;
end;


e no botão adicionar você coloca:
TForm1.bbAdd(Sender: TObject);
begin
  Lista.Add(IntToStr(SpinEdit1.Value));
  Edit1.Text := Edit1.Text + ´;´ + IntToStr(SpinEdit1.Value);
end;


pronto. Agora você tem como adicionar números e apagar todos os números. Agora, temos que fazer a nossa função para calcular quais os possíveis valores. Então coloque um botão com caption Possíveis valores e um memo, não esquecendo de limpar apagar o ´Memo1´ que vem na propriedade Lines. Ai você faz a função recursiva da seguinte maneira:
procedure ShowNumber(aIndex: integer);
var
  cont: integer;
  index: integer;
  temp: string;
begin
  cont := 0;
  while cont < Lista.Count-1 do
  begin
    temp := Lista[aIndex];
    index := aIndex + cont;
    while Length(temp) < Lista.Count do
    begin
      if index >= Lista.Count-1 then
        index := 0
      else
        inc(index);
      if index = aIndex then
        continue;
      temp := temp + Lista[index];
    end;
    memo1.lines.add(temp);
    inc(cont);
  end;

  if aIndex < Lista.Count -1 then
  begin
    Inc(aIndex);
    ShowNumber(aIndex);
  end;


e então você chama a função no seu botão que vai mostrar os valores
var
  index: integer;
begin
  index := 0;
  memo1.Clear;
  ShowNumber(index);
end;



GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Muito obrigado amigos, problema resolvido!


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Amigo Zerneo, o que você me passou foi de muita utilidade.
Agora, sem querer abusar muito, como faço para ele colocar os números em uma certa ordem, por exemplo:
se eu escolher os números 1 3 5 7 10 combinado em terno, ele deverá mostrar:

1 3 5
1 3 7
1 3 10
1 5 7
1 5 10
1 7 10

Sempre em oerdem crescente e sem repetir combinações.

você poderia me dar um help?

Muito obrigado!


GOSTEI 0
Rafael Heise

Rafael Heise

10/11/2003

Eu acredito que ele já faça na ordem....
não entendi o que você quis..
mas pra qualquer caso, ao invés de adicionar direto no memo, adicione numa TStringList, e antes de passar para o memo chame o procedimento Sort; da StringList. Ele vai ordenar os items da StringList e então passe a StringList para o Memo
memo.lines.AddStrings(Lista);
beleza?


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

Zerneo,

eu entendi o que quis dizer, mas o que acontece é o seguinte:
Se, por exemplo, o usuário escolher os números 1 3 5 7 combinado em terno, gostaria que o resultado fosse:

1 3 5
1 3 7
1 5 7

mas o resultado que sua função está me retornando é:

1 3 5
1 5 7
1 7 3
3 5 7
3 7 1
3 1 5
5 7 1
5 1 3
5 1 3
7 1 3

Minhas dúvidas são: Como não deixar duplicar os resultados, exemplo:
1 7 3 = 7 1 3

Desculpe pela amolação Zerneo, mas estou tendo dificuldades e meu prazo está terminando!

Muito obrigado pela atenção!


GOSTEI 0
Rafael Heise

Rafael Heise

10/11/2003

A minha função na verdade está retornando sempre todos os possíveis numeros. Então se você informar 4 valores, ele vai te devolver todas as possíveis combinações de 4 valores.
Tem que ver como fazer do jeito que você quer...
não sei assim ... tem que parar e pensar... e agora eu estou cheio de coisas pra fazer e não vou poder parar...
me desculpe...
assim que eu puder eu te ajudo...
foi mal...

não me entenda mal, não estou negando ajuda, mas aqui no meu trabalho tenho algumas coisas pra fazer e tenho que dar prioridade pra isso.
Vou terminar minhas coisas e ver o que posso fazer pra te ajudar.. valeu


GOSTEI 0
Anarchybra

Anarchybra

10/11/2003

beleza Zerneo, agradeço.


GOSTEI 0
POSTAR