Pular para o conteúdo principal

Postagem em destaque

BlackTDN :: LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring

_Créditos das imagens: ChatGPT_ ### LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring Resolver o problema do [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/description/) é um exercício clássico de programação, que desafia desenvolvedores a encontrar a maior substring palindrômica dentro de uma string. Recentemente, exploramos soluções tanto em Harbour quanto em TLPP (Total Language Protheus Programming). Neste artigo, comparamos as implementações nessas duas linguagens, destacando suas semelhanças, diferenças e funcionalidades específicas. #### Implementações em Harbour ##### Versão 5.1 Essa solução utiliza a técnica de expansão a partir do centro do palíndromo. Cada caractere ou par de caracteres consecutivos é considerado um possível "centro". O algoritmo expande em ambas as direções enquanto os caracteres forem iguais, retornando o maior palíndromo encontrado. ##### Versão 5....

BlackTDN :: Posicione via SDU

SDU :: Siga Database Utility == APSDU :: Advanced Protheus “S” DataBase Utility == MPSDU :: Microsiga Protheus “S” DataBase Utility.

Quem nunca usou essa ferramenta que atire a primeira pedra.

Luizinho “Leitão” da TOTVS RJ aprendeu um cadinho de truques para usar no SDU, dentre eles: o uso da função posicione para um “Replace” via SDU.

Normalmente, quando se abre uma tabela via SDU ela recebe o seguinte “Alias” <Nome da Tabela> + “1”. Então, se abrirmos a tabela CNT010 seu alias será CNT0101.

Por padrão, não podemos abrir 2 vezes a mesma tabela. Mas nada nos impede de abrirmos duas tabelas com o mesmo nome.

Podemos abrir a tabela CNT010 via TOPCONN e a tabela CNT010 via DBFCDXADS/DBFCDXAX. Então, a primeira terá o alias CNT0101 e a segunda CNT0102.

Poderemos abrir tabelas de mesmo nome e para um mesmo RDD se estiverem ambas em localidades diferentes. Neste caso o SDU respeitará o esquema de nomeação de Alias sufixando o nome da tabela com um seqüencial 1, 2,…,n.

No exemplo, e por ser mais didático, utilizarei a tabela SX3 (Dicionário de campos do Protheus).

Vou usar duas tabelas SX3 com o mesmo nome, no mesmo RDD mais em localidades diferentes para efetuar um “Replace” (busca e substituição)  na coluna X3_ORDEM.

Em primeiro lugar vou salvar a tabela SX3010 da pasta \system\ na pasta tmp. Posso fazer isso de n maneiras. Dentre elas: copiando-a diretamente para a pasta, “Importando” (CTRL+T) ou “Copiando para (CTRL+Y) Via SDU . A vantagem de efetuar a cópia via SDU é a possibilidade efetuar um filtro.

Vamos ao exemplo:

Abrindo a tabela SX3010 via SDU usando o RDD (Driver) DBFCDXADS/DBFCDXAX.

image

image

Seleciono a ordem 1 (X3_ARQUIVO+X3_ORDEM)

image

E, agora, utilizando a opção “Copiar Para CTRL+Y” efetuo a cópia. Vou usar o mesmo Driver de Origem.

image

Observe que a sugestão de nome de arquivo segue o padrão de nomeação do Alias. Ou seja, é o nome da tabela sufixada com um número seqüencial. No nosso exemplo, como existe apenas uma tabela SX3010 aberta, o seu sufixo será “1”. Clico no botão OK e a cópia tem início. Neste caso todos os registros serão copiados pois nenhum filtro foi implementado. Vale lembrar, também, do estado de SET DELETED. Se ligado ou Desligado para a cópia, inclusive, dos registros “Deletados”.

image

Após a cópia uma mensagem com o número de registros “copiados” é mostrada conforme abaixo:

image

Considerando que a Ordem selecionada para a “Cópia” foi a 1, os registros foram fisicamente gravados na seqüencia X3_ARQUIVO + X3_ORDEM.

Agora, para que o exemplo fique mais didático, eu vou, primeiro, eliminar todos os registros da tabela SX3010 corrente (uma vez que já efetuei a cópia) utilizando a opção “ZAP CTRL+Z” para posterior “Append” na Ordem em que a cópia foi gravada.

image

Pronto. Minha tabela está limpinha e pronta para os testes.

image

Vou aproveitar a deixa e “Fechar” todos os índices da Tabela Corrente. Índice\Fechar. Isso porque, minha próxima ação será importar os registros de acordo com a Ordem de Gravação e depois efetuar o “Replace” no campo X3_ORDEM e, considerando que o campo X3_ORDEM faz parte da chave, se a mantiver aberta o processo não será concluído com sucesso.

image

Efetuando o “Append CTRL+A”:

image

Irei “Importar” os registros da tabela selecionada. No caso: a tabela anteriormente “copiada”.

image

Pronto. A tabela foi “repopulada”

.image

E, agora, usando a expressão ADVPL abaixo vou reordenar (Alterar o conteúdo do campo X3_ORDEM) de forma seqüencial e de acordo com X3_ARQUIVO de forma todos os intervalos sejam preenchidos.

IF(Type("x3o")=="C".and.xAlias==X3_ARQUIVO,x3o:=__Soma1(x3o),(xAlias:=X3_ARQUIVO,x3o:="01"))

Destrinchando a expressão ADVPL acima teremos: Usando a função condicional IF (equivalente a IIF) verifico se a variável “x30” está definida através da função Type que me retornará “C” se verdadeiro e “U” caso contrário. Se o retorno de Type() for “U” e o conteúdo de xAlias (ainda não declarada) for igual ao conteúdo da coluna/campo X3_ARQUIVO ele irá atribuir à coluna X3_ORDEM o retorno da atribuição x3o :=__Soma1(x3o), caso contrário, irá: 1 declarar (se ainda não estiver definida a variável xNome) é atribuir-lhe o conteúdo de X3_ARQUIVO e setar o conteúdo da variável x3o com “01” (valor inicial da seqüência).

Usando a opção “Replace CTRL+R”

image

(Obs.: A opção “Replace”, como todas as outras, poderiam ser melhoradas se já pré-selecionassem o campo de acordo com a coluna em foco. Normalmente a seleção  manual e a desatenção são a maior causa de problemas nesse tipo de operação).

image

image

Bem, todos os 70106 registros foram “reordenados”. Agora, ao uso da Posicione para restaurar a “Ordem” original.  Para isso, vamos, agora, “Abrir CTRL+B” a tabela SX30101 salva em \tmp\.

image

Ambas as tabelas SX3 estão abertas. Vamos prepara-las para a Posicione.

image

Mas antes, vamos descobrir qual o Alias atribuído à tabela SX30101. Para isso, basta simular uma “Cópia CTRL+Y” e o SDU nos mostrará qual Alias foi atribuído à tabela SX30101.

image

Sabemos, agora, o Alias atribuído à tabela SX30101: sx301011 (que segue a regra de atribuição anteriormente apresentada). Se a nova tabela aberta fosse SX3010 ao invés de SX30101 seu Alias seria SX30102 ao invés de SX301011. (Não precisamos confirmar a cópia e clicamos no botão “cancelar”).

Para que seja possível usar a função Posicione na tabela SX30101 ela deverá estar devidamente ordenada. Então, para isso, iremos criar um índice temporário: Índice\Criar

image

O índice será um índice temporário com as colunas X3_ARQUIVO+X3_CAMPO:

image

(Observe que para o índice ele atribui o mesmo nome do arquivo alterando, apenas, a sua extensão quando o Driver (RDD Controlador) é o DBFCDXADS/DBFCDXAX.)

image

Para o exemplo, indexamos apenas a tabela na qual a Posicione será utilizada, que é a tabela com a “Ordem Original”.

image

Agora, para que a Posicione funcione corretamente, os procedimentos abaixo deverão ser seguidos à RISCA:

  1. Selecione a Tabela na qual efetuará o “Replace CTRL+R”;
  2. Posicione o Ponteiro do Mouse na Primeira Linha da Tabela para que o “Replace” seja efetuado a partir da linha corrente;
  3. Monte a Expressão “Com” para o “Replace CTRL+R”;
    Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_ORDEM")
  4. Monte a Expressão “Para” com  a “Condição do Replace”;
    (Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_CAMPO")==SX30101->X3_CAMPO)

    Efetuando o “Replace”

    image

    image

    Observe que, por distração, o “Replace” foi executado na coluna/campo X3_ARQUIVO quando o correto seria na coluna X3_ORDEM. Desespero?!??!?! Não. No mínimo 2 (duas) soluções possíveis:

    image

    1. Copiar a Tabela SX30101 para SX3010 ; ou
    2. Efetuar o ZAP na Tabela SX3010, efetuar o Append dos Dados da tabela SX30101 e reordena-los ; ou
    3. Efetuar o Replace na Coluna X3_ARQUIVO de forma a restaura-la à sua situação original. (ainda bem que foi esse o campo) usando a seguinte regra:
      IF(SubStr(X3_CAMPO,3,1)=="_","S"+SubStr(X3_CAMPO,1,2),SubStr(X3_CAMPO,1,3))

      Pois a regra de formação do campo é: se o primeiro byte do Alias for “S” o campo não terá o “Alias” completo será SubStr(X3_ARQUIVO,2,2)+_+campo, caso contrário, a formação do campo será X3_ARQUIVO+_+campo.

    image

    image

    Ufa. Agora que restauramos o conteúdo do campo X3_ARQUIVO vamos ao “replace” da coluna X3_ORDEM usando Posicione.

    Mas, antes, vamos contar quantos registros foram alterados com a reordenação do campo X3_ORDEM usando a seguinte regra:

    !(Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_ORDEM")==SX30101->X3_ORDEM)

    image 

    image

    image 

    e, finalmente. Restaurar a Ordem “Original”

    image

    image

    image

    Após o “Replace”, se efetuarmos a contagem anterior deveremos obter o valor 0 (Zero)

    image

    image

    Pronto. Ordem restaurada.

    ATENÇÃO :: Vale lembrar que qualquer operação efetuada diretamente no SDU deve ser feita com muita atenção e após garantir uma cópia da tabela original.

    As expressões ADVPL utilizadas no exemplo foram:

    1 - Para “Reordenar” o campo X3_ORDEM utilizando a função __Soma1()
    IF(Type("x3o")=="C".and.xAlias==X3_ARQUIVO,x3o:=__Soma1(x3o),(xAlias:=X3_ARQUIVO,x3o:="01"))
    2 - Retorno da Expressão do Replace “Com”
    Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_ORDEM")
    3 - Condição do Replace “Para”
    (Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_CAMPO")==SX30101->X3_CAMPO)
    4 - Restaurar o conteúdo do campo X3_ARQUIVO
    IF(SubStr(X3_CAMPO,3,1)=="_","S"+SubStr(X3_CAMPO,1,2),SubStr(X3_CAMPO,1,3))
    5 - Contar o número de registros afetados pela expressão em 1
    !(Posicione("SX301011",1,SX30101->(X3_ARQUIVO+X3_CAMPO),"X3_ORDEM")==SX30101->X3_ORDEM)

    []s
    иαldσ dj

    Comentários

    1. Preciso alterar no campo R8_DTFIM, somente o ano
      Exemplo:
      R8_DTFIM = 31/01/2014
      IF(SUBSTR(CTOD(RFQ_DTFIM,5,4)=="2014"),"2013") ISSO É POSSIVEL via APSDU?

      ResponderExcluir
    2. IF(SUBSTR(CTOD(RFQ_DTFIM,5,4)=="2014"),"2013"), e possível incluir essa função via APSDU para mudar somente o campo DATA,

      ResponderExcluir

    Postar um comentário

    Postagens mais visitadas