Postagem em destaque

Huguinho e Zezinho surfando com granizo

Imagem
Certa vez, em outubro de 2023, Huguinho e seu amigo Zezinho foram surfar no final da tarde. O vento estava forte e a chuva, constante. Quando chegaram perto da praia, mal conseguiam segurar suas pranchas. O mar estava bem mexido, e ainda tiveram que andar cerca de 1 km até o pico. Quando estavam se aproximando, começou a cair granizo! Dava para ouvir claramente o barulho das pedras contra as pranchas. Eles se abrigaram embaixo do posto avançado dos salva-vidas, mas não adiantou muito. Ficaram olhando o mar — que estava bem agitado e quebrando bem longe — e perceberam que estava difícil passar a arrebentação. Como o granizo não parava, decidiram entrar assim mesmo. Logo que entraram no mar, o granizo cessou, mas aí começou o verdadeiro desafio: passar a arrebentação. Depois de levar várias séries na cabeça e quase sem forças, finalmente conseguiram. E começaram os raios! Quando estavam quase decidindo sair por causa deles, os raios pararam. Ufa! É algo estranho: você está lá, só você (c...

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

Google Hacking

Netflix não mostra ícone de streaming

Radar no KM 175 da BR101