Postagem em destaque

A incrível velocidade do Go

Imagem
Um dos motivos que gosto do Go (a linguagem de programação, não o jogo), é que ele é extremamente rápido. E não estou falando de utilizar goroutines pois aí é covardia. Estamos migrando um sistema de Coldfusion para Go e PHP e uma das rotinas insere um registro no banco de dados no início e outra no fim do processo. Pense como se fosse um log, mas um log específico para essa rotina. Dessa forma: 2023-05-18 17:45:03. 687     ... [processaImagem] Incorporando imagem 2023-05-18 17:45:03. 688     ... [processaImagem] Imagem incorporada Entre o inicio e o final do processamento levou 1ms. Até aí, tudo bem, se não fosse o fato dessa tabela ter o campo timestamp como parte da chave primária. Se reparar, o tempo é definido em milissegundos. Com o Coldfusion esse processo dura cerca de 20ms. Simplesmente migrando para Go, o tempo caiu muito, para menos de 1ms e assim, começou a dar erro de chave duplicada. A solução? Depende, sempre depende. No nosso contexto, a mais simples foi feita, pois nã

Quadrado Mágico - Parte 1

Irei publicar uma série de postagens sobre algoritmos para resolução dos Quadrados Mágicos. A postagem de hoje é bem simples e tem algumas limitações (por exemplo, só aceita quadrados de grau 3). Mas minha intenção é justamente essa: pegar o algoritmo e ir tornando-o mais complexo e mais genérico. No futuro, tentarei adaptar esse algoritmo para resolução de outro quebra-cabeças que gosto muito: SUDOKU. Mas vamos ao que interessa, que é o código do programa. Desenvolvi em Delphi, mas ele é simples e facilmente adaptável a outras linguagens:
{$APPTYPE CONSOLE}
program qm;

uses
SysUtils, Windows, Dialogs, Math, Forms;

const
GRAU  = 3;  // Grau do quadrado
GRAU2 = GRAU*GRAU;  // Total de elementos do quadrado                             
TOTAL = (((1 + GRAU2) * GRAU2) div 2) div GRAU; // Soma total a ser alcançada

type
  TAQuad = array[1..GRAU2] of integer;  // Tipo Quadrado

var
  q: TAQuad;
  limite: int64;
      
// --------------------------------------------------------
// Mostra o resultado na tela
// --------------------------------------------------------
procedure Show();
var
  lin, col: integer;
  pos: integer;
begin;
  pos := 0;
  for lin := 1 to GRAU do begin
    for col := 1 to GRAU do begin
      inc(pos);
      Write(q[pos]:4);
    end;
    Writeln;
  end;
end;


// --------------------------------------------------
// avalia meta
// --------------------------------------------------
function goal(): boolean;
var
  x, y: integer;
  px, py, dp, ds: integer;
  sl, sc: array[1..GRAU] of integer;

begin      
  result := false;

  FillChar(sl, sizeof(sl), 0);
  FillChar(sc, sizeof(sc), 0);

  dp := 0;
  ds := 0;

  px := 1;
  py := GRAU;

  for x := 1 to GRAU do begin
    // soma diagonais
    inc(dp, q[px]);
    inc(ds, q[py]);
    inc(px, succ(GRAU));
    inc(py, pred(GRAU));

    // soma linhas e colunas
    for y := 1 to GRAU do begin
     inc(sl[y], q[GRAU * pred(x) + y]);
     inc(sc[y], q[GRAU * pred(y) + x]);
    end;
  end;

  // verifica se cada linha e coluna são válidas
  for x := 1 to GRAU do
    if (sl[x] <> TOTAL) or (sc[x] <> TOTAL) then exit;

  // verifica se as diagonais são válidas
  if (dp <> TOTAL) or (ds <> TOTAL) then exit;

  result := true;
end;



// --------------------------------------------------
// retorna próximo número
// --------------------------------------------------
function next(n: int64): int64;
var
  i:   integer;
  s:   string;
  erro: boolean;
  rep:  TAquad;

begin         
  repeat
    inc(n);

    // transforma o número em string
    s := inttostr(n);

    // inicialmente, não tem erro
    erro := false;

    // inicializa array de repetições
    FillChar(rep, sizeOf(rep), 0);

    // não permite números repetidos
    for i := 1 to GRAU2 do begin
      // não permite zeros
      if s[i] = '0' then begin
        erro := true;
        break;
      end;      

      // joga o número para o array
      q[i] := ord(s[i])-48;

      // conta número de repetições
      inc(rep[q[i]]);

      // verifica se repetiu o número
      if rep[q[i]] > 1 then begin
        erro := true;
        break;
      end;  
    end;
 
    // erro encontrado, avança para o próximo número
    if erro then continue;

    // sai do laço
    break;
  until n > limite;// executa no máximo até o limite de 10^GRAU2-1

  result := n;
end;



// --------------------------------------------------
// Rotina principal
// --------------------------------------------------
var
  inicio: int64;
  n:   int64;

begin
  // início do processamento
  inicio := GetTickCount;   

  // primeiro número válido
  n := round(power(10, GRAU2-1)) - 1;

  // útimo número válido
  limite := round(power(10, GRAU2)) - 1;       

  // laço principal
  repeat
    //Processa mensagens pendentes do Windows
    Application.ProcessMessages;

    // próximo número a ser testado
    n := next(n);

    // verifica se atingiu a meta
    if goal() then begin    
      show(); // mostra o quadrado
      break;
    end;
  until n > limite;// executa no máximo até o limite de 10^GRAU2-1

  // mostra o tempo de processamento
  writeln('Tempo (s): ' + inttostr((GetTickCount - inicio) div 1000));
  readln;
end.

Comentários

Postagens mais visitadas deste blog

Netflix não mostra ícone de streaming

Google Hacking

FTP não funciona no PHP