Página 1 de 3

vetor: busca maior número

Enviado: 17 Jun 2021 01:24
por cjp
Pessoal, estou precisando de uma ajuda.
Preciso encontrar um número entre 9 variáveis, que atenda às seguintes especificações: o número precisa ser o maior nvenc possível, desde que o nmelh seja igual ou maior que o dia atual.

Criei um vetor assim:

Código: Selecionar todos

		 aadd(nvestr,{crt1,nvenc1,nmelh1})
		 aadd(nvestr,{crt2,nvenc2,nmelh2})
		 aadd(nvestr,{crt3,nvenc3,nmelh3})
		 aadd(nvestr,{crt4,nvenc4,nmelh4})
		 aadd(nvestr,{crt5,nvenc5,nmelh5})
		 aadd(nvestr,{crt6,nvenc6,nmelh6})
		 aadd(nvestr,{crt7,nvenc7,nmelh7})
		 aadd(nvestr,{crt8,nvenc8,nmelh8})
		 aadd(nvestr,{crt9,nvenc9,nmelh9})
Como faço para pegar o registro que atenda aos requisitos antes enunciados?

Alguém pode me ajudar?

vetor: busca maior número

Enviado: 17 Jun 2021 15:08
por alxsts
Olá!
cjp escreveu:Alguém pode me ajudar?
Poste este array contendo alguns valores para que tenhamos uma ideia dos tipos de dados que ele contem.

vetor: busca maior número

Enviado: 17 Jun 2021 16:50
por cjp
A array contém apenas o nome (campo com até 15 caracteres) e dias (os campos nvenc e nmelh são campos numéricos com até dois dígitos).

Exemplo:

XXXXXXXXX, 01, 22
yyyyyyyyyy, 05, 25
ZZZZZZZZZ, 08, 31
etc.

vetor: busca maior número

Enviado: 17 Jun 2021 21:18
por JoséQuintas
cjp escreveu:Preciso encontrar um número entre 9 variáveis, que atenda às seguintes especificações: o número precisa ser o maior nvenc possível, desde que o nmelh seja igual ou maior que o dia atual.
Tô achando a pesquisa esquisita, mas....

O maior vencimento, com número igual ou maior.
Se pensar no MySQL e ORDER BY....

Primeiro é ordenar esse array por vencimento decrescente, e dia decrescente.
Depois é pegar o primeiro que encontrar, com número maior ou igual ao dia atual, sem nem precisar comparar data pra saber qual é maior.

Em MySQL seria
SELECT * FROM tabela WHERE NUMERO >= diaatual ORDER BY DATA,DIA DESC

Em array, o ASort() pra colocar em ordem, e o ASCan() pra pesquisar.

Legal né.... acaba sendo a mesma lógica.

Exatamente o que comentei em outro post: é tudo tabela, apenas nunca pensamos nisso, mas o SQL pensou.

vetor: busca maior número

Enviado: 17 Jun 2021 21:29
por alxsts
Olá!

Teste isto:

Código: Selecionar todos

#include "inkey.ch"

FUNCTION Main()

   LOCAL nDay, GetList := {}

   SetMode( 25,80 ) ; CLS

   nDay := Day( Date() )

   While Lastkey() != K_ESC
      @ 10,10 Say "Informe o dia    :" ;
              Color "W+/B" ;
              Get nDay ;
              Color "W+/B, B+/W" ;
              Pict "99" ;
              VALID nDay > 0 .And. nDay < 32
      READ

      @ 12,10 Say "Valor encontrado : " + Transform( BuscaVal( nDay ), "@99" ) Color "W+/B"

      @ 16,10 Say "Tecle algo..." Color "W+/B" 

      Inkey(0)

      @ 12,10 CLEAR TO 16,70
   Enddo

RETURN NIL
//------------------------------------------------------------------------------------------

// Posições em aArray
#define A_DESCRIÇAO    1
#define A_VENCIMENTO   2
#define A_MELHOR_DIA   3

FUNCTION BuscaVal( nDay )

   LOCAL aArray, e, nMax

   aArray := { { "Lorem ipsum sod",  1,  2 }, ;
               { "ales senectus ",   5,  4 }, ;
               { "donec sociosqu ", 10,  6 }, ;
               { "scelerisque ",    15,  8 }, ;
               { "pharetra primis", 20, 10 }, ;
               { "blandit odio ",   25, 12 }, ;
               { "dui massa ",      30, 14 }, ;
               { "vivamus ",         2, 16 }, ;
               { "himenaeos ",       7, 18 }, ;
               { "euismod ac ",     12, 20 }, ;
               { "semper ",         19, 22 }, ;
               { "facilisis vitae", 26, 24 }, ;
               { "sagittis ",       31, 15 }, ;
               { "faucibus ",        3, 28 }, ;
               { "viverra ",         8, 30 }, ;
               { "vestibulum nisi", 13,  1 }, ;
               { "sodales congue",  18,  3 }, ;
               { "dolor quisque",   23,  5 }, ;
               { "amet",            28,  7 }, ;
               { "gravida augue",    4,  9 }, ;
               { "luctus ut vel",    9, 11 }, ;
               { "tellus potenti",  14, 13 } ;
             }

   nMax := 0

   // Para cada elemento e no aArray...
   For Each e In aArray
      // Cada elemento também é um array...
      // Se a terceira posição do elemento for maior ou igual ao dia em nDay...
      If e[ A_MELHOR_DIA ] >= nDay
         // Se a segunda posição do elemento for maior que o anterior,
         // guarda o valor da segunda posição do elemento
         nMax := If( e[ A_VENCIMENTO ] > nMax, e[ A_VENCIMENTO ], nMax )
      Endif
   Next

RETURN nMax
//------------------------------------------------------------------------------------------

vetor: busca maior número

Enviado: 17 Jun 2021 21:32
por cjp
Não estou usando MySQL neste caso. Os dados estão diretamente no prg mesmo.
O problema é que eu não sei lidar bem com vetores. Nem sei se a melhor forma de fazer isso é mesmo com vetor.
Se for necessário, posso criar uma tabela no MySQL para extrair os dados da forma como vc disse. Mas, se for possível evitar isso, seria melhor.

vetor: busca maior número

Enviado: 17 Jun 2021 21:51
por JoséQuintas
É que como não faz parte do dia a dia, também tenho que pesquisar.
Talvez ajude pensar como falei, o array é uma tabela com campos, ao invés de nomes são números.
Me confundo se é > ou <
E também se no ASCan() é mesmo assim, ou se só no hb_AScan() aceita codeblock no primeiro parâmetro.

Código: Selecionar todos

#define ITEM_DATA 2
#define ITEM_DIA   3

FUNCTION MelhorDia( nDiaAtual )

LOCAL aList := { .... }
LOCAL nPos

ASort( aList, { | a, b | a[ ITEM_DATA ] > b[ ITEM_DATA ] .OR. ( a[ ITEM_DATA ] == b[ ITEM_DATA ] .AND. a[ ITEM_DIA ] > b[ ITEM_DIA ] ) } )

nPos := AScan( aList, { | e | e[ ITEM_DIA ] >= nDiaAtual } )

RETURN aList[ nPos, ITEM_DATA ]
Nota: Editado pra corrigir o resultado pra data, e não posição numérica.

vetor: busca maior número

Enviado: 17 Jun 2021 22:03
por JoséQuintas
Só pra avisar que editei o post anterior, e também pra explicar:

Colocando em ordem de data decrescente e dia decrescente, já vai estar na ordem correta de maior data e maior número.
Desse jeito vai ser o primeiro que encontrar.

o ASort() usa as colunas data e dia pra isso, colunas 2 e 3 (ITEM_DATA e ITEM_DIA)
o ASCan() pesquisa o dia, portanto coluna 3 (ITEM_DIA)
No caso de array, o #define ajuda a usar uma espécie de nome, ao invés de usar o número, o que facilita "não errar".
Como o retorno do ASCan() é a posição (por isso chamei a variável de nPos), é pegar a informação dessa posição.

O array é como o DBF, tem seus registros (1,2,3,...), e cada registro tem seus campos (1,2,3)
o ASort() acaba sendo uma espécie de indexação, mas direta, sem índice.
e o ASCan() acaba sendo uma espécie de SEEK, que retorna o número do registro.
No final é o registro nPos, e o campo 3 (a Data). aList[ nPos, 3 ] ou no fonte com #define, aList[ nPos, ITEM_DATA ]
Talvez pensando desse jeito ajude a entender melhor o array.

vetor: busca maior número

Enviado: 18 Jun 2021 00:36
por cjp
Adaptei aqui e funcionou, mas acho que não corretamente.
Fiz assim:

Código: Selecionar todos

function crtmelh
         local crtm, crt2m, crt3m, crt4m
		 local aList :={}
         LOCAL nPos
         local crt1 :="I...."
		 local nvenc1 :=1
		 local nmelh1 :=23
		 local crt2 :="O...."
		 local nvenc2 :=5
		 local nmelh2 :=28
		 local crt3 :="B...."
		 local nvenc3 :=8
		 local nmelh3 :=24
		 local crt4 :="V..."
		 local nvenc4 :=12
		 local nmelh4 :=2
		 local crt5 :="N..."
		 local nvenc5 :=18
		 local nmelh5 :=11
		 local crt6 :="C..."
		 local nvenc6 :=20
		 local nmelh6 :=10
		 local crt7 :="S..."
		 local nvenc7 :=22
		 local nmelh7 :=10
		 local crt8 :="R..."
		 local nvenc8 :=25
		 local nmelh8 :=11
		 local crt9 :="I..."
		 local nvenc9 :=28
		 local nmelh9 :=18
		 
		 aadd(aList,{crt1,nvenc1,nmelh1})
		 aadd(aList,{crt2,nvenc2,nmelh2})
		 aadd(aList,{crt3,nvenc3,nmelh3})
		 aadd(aList,{crt4,nvenc4,nmelh4})
		 aadd(aList,{crt5,nvenc5,nmelh5})
		 aadd(aList,{crt6,nvenc6,nmelh6})
		 aadd(aList,{crt7,nvenc7,nmelh7})
		 aadd(aList,{crt8,nvenc8,nmelh8})
		 aadd(aList,{crt9,nvenc9,nmelh9})

#define ITEM_DATA 2
#define ITEM_DIA   3

ASort( aList, { | a, b | a[ ITEM_DATA ] > b[ ITEM_DATA ] .OR. ( a[ ITEM_DATA ] == b[ ITEM_DATA ] .AND. a[ ITEM_DIA ] > b[ ITEM_DIA ] ) } )

nPos := AScan( aList, { | e | e[ ITEM_DIA ] >= day(date()) } )

?aList[ nPos, ITEM_DATA ]

inkey(11)
inkey(11)
Não sei se entendi o teu código, já que não entendo muito nem de vetor nem de codeblock.

Por que acho que não deu certo? Porque retornou a posição 1, tanto ontem (dia 17), quanto hoje (dia 18). Sendo que, na minha lógica, deveria retornar a posição 8 ontem e a posição 9 hoje.

Vou precisar pegar não apenas o primeiro, mas os 4 primeiros.

Outra dúvida: como faço para pegar o elemento crt?

vetor: busca maior número

Enviado: 18 Jun 2021 10:06
por JoséQuintas

Código: Selecionar todos

#define ITEM_NOME 1
#define ITEM_DATA 2
#define ITEM_DIA  3

PROCEDURE Main

   LOCAL aItem

   SetMode(40,100)
   CLS
   Altd()
   aItem := CrtMelhor( Date() )
   ? aItem[ ITEM_NOME ]
   ? aItem[ ITEM_DATA ]
   ? aItem[ ITEM_DIA ]
   Inkey(11)

   RETURN

FUNCTION CrtMelhor( dData )

   LOCAL nPos, aList := { ;
      { "I....", 1, 23 }, ;
      { "O....", 5, 28 }, ;
      { "B....", 8, 24 }, ;
      { "V...", 12, 2 }, ;
      { "N...", 18, 11 }, ;
      { "C...", 20, 10 }, ;
      { "S...", 22, 10 }, ;
      { "R...", 25, 11 }, ;
      { "I...", 28, 18 } }

   ASort( aList,,,{ | a, b | a[ ITEM_DATA ] > b[ ITEM_DATA ] .OR. ( a[ ITEM_DATA ] == b[ ITEM_DATA ] .AND. a[ ITEM_DIA ] > b[ ITEM_DIA ] ) } )

   nPos := AScan( aList, { | e | e[ ITEM_DIA ] >= Day( dData ) } )

   RETURN aList[ nPos ]
Ok, tinha errado sobre como colocar o parâmetro no Asort()

Na lista, tem melhor 10, com dias 20 e 22, o dia 20 nunca vai ser usado.
Na lista, tem melhor 11, com dias 18 e 25, o dia 18 nunca vai ser usado.
Tem certeza sobre a escolha? faltou mencionar alguma coisa?

vetor: busca maior número

Enviado: 18 Jun 2021 10:11
por JoséQuintas
O que achei estranho na forma que decidiu usar:

dias 1 a 18, retorna 28
dias 19 a 24, retorna 8
dias 25 a 28, retorna 5
acima disso, não retorna nada.

Faltou mencionar alguma coisa sobre seu critério.

vetor: busca maior número

Enviado: 18 Jun 2021 10:18
por JoséQuintas
Teste prático:

Código: Selecionar todos

PROCEDURE Main

   LOCAL aItem, nDia

   SetMode(40,100)
   CLS
   Altd()
   FOR nDia = 1 TO 30
      aItem := CrtMelhor( Stod( "202106" + StrZero( nDia, 2 ) ) )
      ? nDia, aItem[ ITEM_NOME ], aItem[ ITEM_DATA ], aItem[ ITEM_DIA ]
   NEXT
   Inkey(11)

   RETURN
result.png
Então, de acordo com o que disse no primeiro tópico, seria isso.
Desse jeito, mais prático um IF/ELSE com 3 IFs.

vetor: busca maior número

Enviado: 18 Jun 2021 11:35
por JoséQuintas
Outra coisa:
Não tem vencimento ANTES da emissão, então, trabalhar apenas com o dia não vai dar certo.
Mas ok, se o vencimento for menor que a emissão, seria mudar para o mês seguinte.

Acho que esse é mais um daqueles casos pra colocar no papel primeiro, pra ver se o que está pedindo é realmente o que está querendo como resultado.

vetor: busca maior número

Enviado: 18 Jun 2021 12:19
por JoséQuintas
Só pra constar, o fonte atualizado que usei no último teste.

Código: Selecionar todos

##define ITEM_NOME 1
#define ITEM_DATA 2
#define ITEM_DIA  3

PROCEDURE Main

   LOCAL aItem, nDia

   SET DATE BRITISH
   SetMode(40,100)
   CLS
   Altd()
   FOR nDia = 1 TO 30
      aItem := CrtMelhor( Stod( "202106" + StrZero( nDia, 2 ) ) )
      ? nDia, aItem[ ITEM_NOME ], aItem[ ITEM_DATA ], aItem[ ITEM_DIA ], Stod( "2021" + iif( aItem[ ITEM_DATA ] >= nDia, "06", "07" ) + StrZero( aItem[ ITEM_DIA ], 2 ) )
   NEXT
   Inkey(11)

   RETURN

FUNCTION CrtMelhor( dData )

   LOCAL nPos, aList := { ;
      { "I....", 1, 23 }, ;
      { "O....", 5, 28 }, ;
      { "B....", 8, 24 }, ;
      { "V...", 12, 2 }, ;
      { "N...", 18, 11 }, ;
      { "C...", 20, 10 }, ;
      { "S...", 22, 10 }, ;
      { "R...", 25, 11 }, ;
      { "I...", 28, 18 } }

   ASort( aList,,,{ | a, b | a[ ITEM_DATA ] > b[ ITEM_DATA ] .OR. ( a[ ITEM_DATA ] == b[ ITEM_DATA ] .AND. a[ ITEM_DIA ] > b[ ITEM_DIA ] ) } )

   nPos := AScan( aList, { | e | e[ ITEM_DIA ] >= Day( dData ) } )
   IF nPos == 0
      RETURN { "nada", 0, 0 }
   ENDIF

   RETURN aList[ nPos ]
Alterei a função pra retornar a linha inteira, assim tem o nome também, e alterei pra retornar "nada" quando não encontra.
result.png
Nota: Só vale pra JUNHO, porque nem me preocupei em servir pra outros meses, por achar que isso vai ser diferente.

vetor: busca maior número

Enviado: 18 Jun 2021 13:28
por cjp
Ainda vou analisar e testar teus últimos posts, e também o do alxsts acima, mas vou adiantar uma informação: não vai ficar nenhum dia sem não.

Vou tentar ser mais claro: cada crt (crt1, crt2, etc) é um cartão, que tem uma data de vencimento (nvenc) e uma data de melhor dia de compra (nmelh).

Então, preciso pegar em cada dia qual cartão tem a data de vencimento mais distante (maior nvenc), desde que esteja no seu melhor dia de compra ou posterior.

Seria simples se todos os cartões tivessem igual distância entre a data de vencimento e a data de melhor compra. Ex: se fosse sempre de 10 dias a diferença, então o cartão que vence dia 25 teria melhor data em 15, o que vence dia 30 teria melhor data em 20, e assim por diante. Assim seria simples de fazer.

Mas infelizmente na prática não é assim. São bem variadas. E pode acontecer (e de fato acontece) de um cartão com vencimento posterior ter melhor data de compra antes de outro que tem vencimento anterior (ex: o de vencimento dia 25 tem melhor data de compra dia 10; o de vencimento dia 22 tem melhor data de compra dia 17). Neste caso o segundo cartão (com vencimento dia 22) será sempre segunda opção, jamais primeira. É isso que complica a questão, e é pra isso que estou me batendo com vetor (que não entendo bem).

Fiz-me entender?

Não vai ficar nenhum dia sem porque no dia 30, por exemplo, usaremos o crt2, cuja melhor data é o dia 28.

No papel, isso está certo. E eu até continuaria com isso só no papel. O problema é que essas datas/cartões sempre variam. Daí toda hora eu tenho que ficar refazendo, e isso dá um trabalho razoável. Por isso tive a ideia de fazer isso automaticamente. Para isso eu preciso quebrar a cabeça com esse vetor, para automatizar esse cálculo. Cada vez que mudar, eu só altero as datas e ele já calcula tudo automaticamente.