unit U_MostAll3;

interface

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

type
  TForm1 = class(TForm)
    DumbWayBtn: TButton;
    ListBox1: TListBox;
    StopBtn: TButton;
    SmartWayBtn: TButton;
    Memo1: TMemo;
    Panel1: TPanel;
    procedure DumbWayBtnClick(Sender: TObject);
    procedure StopBtnClick(Sender: TObject);
    procedure SmartWayBtnClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses math;

procedure adjustListboxtext(s1,s2,s3:string;listbox:TListbox);
{Align s1,s2,s3 into columns and add string to listbox}
var
  thirds:integer;
  s:string;
Begin
  thirds:=listbox.width div 4;
  with listbox do
  Begin
    {pad out the input strings to right align them}
    while canvas.textwidth(s1)<=thirds do s1:=' '+s1;
    while canvas.textwidth(s2)<=thirds do s2:=' '+s2;
    while canvas.textwidth(s3)<=thirds do s3:=' '+s3;
    s:=s1+s2+s3;
    items.add(s);
  end;
end;

procedure TForm1.DumbWayBtnClick(Sender: TObject);
{User clicked "Dumb way"}
var
  start:int64;
  nbr3,k:int64;
  i:integer;
  s,s1,s2,s3:string;
  x:single;
begin
  screen.cursor:=crHourglass;
  listbox1.clear;
  tag:=0;
  start:=1;
  i:=0;
  AdjustListBoxText('N    ','# with "3"s','% with "3"s',listbox1);
  {10 billion ought to be enough - user will hit stop before then}
  while (i<=10) and (tag=0) do
  Begin
    inc(i);
    nbr3:=0; {count of 3's}
    k:=0;  {nbr to be tested}
    while k<=start do
    Begin
      inc(k);
      s:=inttostr(k);  {make it a string and scan for a '3'}
      if pos('3',s)>0 then inc(nbr3);
      if k mod 10000 =0 then  {call processmessges once in a while}
      Begin
        application.processmessages;
        if tag=1 then break;  {user hit the stop button}
      end;
    end;
    
    if tag=0 then  {we finished that size OK - show results}
    Begin
      x:=100*(nbr3/start); {5 of nbrs with 3's}
      start:=start*10; {get next start, also upper limit for decade just completed}
      s1:=format('%12d',[start]); {format nbr}
      s2:=format('%12d',[nbr3]); {format count of 3's}
      s3:=format('%8.1f%%',[x]); {format % of nbrs with 3's}
      adjustlistBoxText(s1,s2,s3,listbox1); {add line to output}
      application.processmessages;
    end;
  end;
  screen.cursor:=crDefault;
end;

procedure TForm1.StopBtnClick(Sender: TObject);
{User clicked Stop button}
begin
  tag:=1;
end;

procedure TForm1.SmartWayBtnClick(Sender: TObject);
var
  i:integer;
  n1,n2,n3:extended;
  x:extended;
  s1,s2,s3:string;
begin
  listbox1.clear;
  AdjustListBoxText('N    ','# with "3"s','% with "3"s',ListBox1);
  n1:=1; n2:=1;
  for i:= 1 to 100 do {i is the power of 10 to start}
  Begin
    x:=100*(1-(Power(0.9,i))); {percent of numbers with 3's}
    If i<=6 then
    Begin  {up to 1,000,000 show number}
      n1:=N1*10;
      n2:=n2*9;
      n3:=n1-n2;
      s1:=format('%12.0n',[n1]);
      s2:=format('%12.0n',[n3]);
      s3:=format('%8.1f%%',[x]);
      adjustlistBoxText(s1,s2,s3,listbox1);
    end
    else {Nbrs getting large, switch to putting out power of N and % only}
    Begin
      If i=7 then {Put out some header data}
      Begin
        listbox1.items.add(' ');
        AdjustListBoxText('Power of  N','','Percent with "3"s',ListBox1);
      end;
      s1:=format('%12d',[i]);
      s2:=format('%8.4f%%',[x]);
      adjustlistBoxText(s1,'',s2,listbox1);
    end;
  end;
end;
end.