Brazilian numbers are so called as they were first formally presented at the 1994 math Olympiad Olimpiada Iberoamericana de Matematica in Fortaleza, Brazil.

Brazilian numbers are defined as:

The set of positive integer numbers where each number N has at least one natural number B where 1 < B < N-1 where the representation of N in base B has all equal digits.



E.G.

 1, 2 & 3 can not be Brazilian; there is no base B that satisfies the condition 1 < B < N-1.
 4 is not Brazilian; 4 in base 2 is 100. The digits are not all the same.
 5 is not Brazilian; 5 in base 2 is 101, in base 3 is 12. There is no representation where the digits are the same.
 6 is not Brazilian; 6 in base 2 is 110, in base 3 is 20, in base 4 is 12. There is no representation where the digits are the same.
 7 is Brazilian; 7 in base 2 is 111. There is at least one representation where the digits are all the same.
 8 is Brazilian; 8 in base 3 is 22. There is at least one representation where the digits are all the same.
 and so on...


All even integers 2P >= 8 are Brazilian because 2P = 2(P-1) + 2, which is 22 in base P-1 when P-1 > 2. That becomes true when P >= 4.

More common: for all all integers R and S, where R > 1 and also S-1 > R, then R*S is Brazilian because R*S = R(S-1) + R, which is RR in base S-1

The only problematic numbers are squares of primes, where R = S. Only 11^2 is brazilian to base 3.

All prime integers, that are brazilian, can only have the digit 1. Otherwise one could factor out the digit, therefore it cannot be a prime number. Mostly in form of 111 to base Integer(sqrt(prime number)). Must be an odd count of 1 to stay odd like primes > 2


Task

Write a routine (function, whatever) to determine if a number is Brazilian and use the routine to show here, on this page;

 the first 20 Brazilian numbers;
 the first 20 odd Brazilian numbers;
 the first 20 prime Brazilian numbers;


See also

 OEIS:A125134 - Brazilian numbers
 OEIS:A257521 - Odd Brazilian numbers
 OEIS:A085104 - Prime Brazilian numbers


 
program Brazilian_numbers;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
  System.SysUtils;
 
type
  TBrazilianNumber = record
  private
    FValue: Integer;
    FIsBrazilian: Boolean;
    FIsPrime: Boolean;
    class function SameDigits(a, b: Integer): Boolean; static;
    class function CheckIsBrazilian(a: Integer): Boolean; static;
    class function CheckIsPrime(a: Integer): Boolean; static;
    constructor Create(const Number: Integer);
    procedure SetValue(const Value: Integer);
  public
    property Value: Integer read FValue write SetValue;
    property IsBrazilian: Boolean read FIsBrazilian;
    property IsPrime: Boolean read FIsPrime;
  end;
 
{ TBrazilianNumber }
 
class function TBrazilianNumber.CheckIsBrazilian(a: Integer): Boolean;
var
  b: Integer;
begin
  if (a < 7) then
    Exit(false);
 
  if (a mod 2 = 0) then
    Exit(true);
 
  for b := 2 to a - 2 do
  begin
    if (sameDigits(a, b)) then
      exit(True);
  end;
  Result := False;
end;
 
constructor TBrazilianNumber.Create(const Number: Integer);
begin
  SetValue(Number);
end;
 
class function TBrazilianNumber.CheckIsPrime(a: Integer): Boolean;
var
  d: Integer;
begin
  if (a < 2) then
    exit(False);
 
  if (a mod 2) = 0 then
    exit(a = 2);
 
  if (a mod 3) = 0 then
    exit(a = 3);
 
  d := 5;
 
  while (d * d <= a) do
  begin
    if (a mod d = 0) then
      Exit(false);
    inc(d, 2);
 
    if (a mod d = 0) then
      Exit(false);
    inc(d, 4);
  end;
 
  Result := True;
end;
 
class function TBrazilianNumber.SameDigits(a, b: Integer): Boolean;
var
  f: Integer;
begin
  f := a mod b;
  a := a div b;
  while a > 0 do
  begin
    if (a mod b) <> f then
      exit(False);
    a := a div b;
  end;
  Result := True;
end;
 
procedure TBrazilianNumber.SetValue(const Value: Integer);
begin
  if Value < 0 then
    FValue := 0
  else
    FValue := Value;
  FIsBrazilian := CheckIsBrazilian(FValue);
  FIsPrime := CheckIsPrime(FValue);
end;
 
const
  TextLabel: array[0..2] of string = ('', 'odd', 'prime');
 
var
  Number: TBrazilianNumber;
  Count: array[0..2] of Integer;
  i, j, left, Num: Integer;
  data: array[0..2] of string;
 
begin
  left := 3;
  for i := 0 to 99999 do
  begin
    if Number.Create(i).IsBrazilian then
      for j := 0 to 2 do
      begin
 
        if (Count[j] >= 20) and (j > 0) then
          continue;
 
        case j of
          0:
            begin
              inc(Count[j]);
              Num := i;
              if (Count[j] <= 20) then
                data[j] := data[j] + i.ToString + ' '
              else
                Continue;
            end;
          1:
            begin
              if Odd(i) then
              begin
                inc(Count[j]);
                data[j] := data[j] + i.ToString + ' ';
              end;
            end;
          2:
            begin
              if Number.IsPrime then
              begin
                inc(Count[j]);
                data[j] := data[j] + i.ToString + ' ';
              end;
            end;
        end;
        if Count[j] = 20 then
          dec(left);
      end;
    if left = 0 then
      Break;
  end;
 
  while Count[0] < 100000 do
  begin
    inc(Num);
    if Number.Create(Num).IsBrazilian then
      inc(Count[0]);
  end;
 
  for i := 0 to 2 do
  begin
    Writeln(#10'First 20 ' + TextLabel[i] + ' Brazilian numbers:');
    Writeln(data[i]);
  end;
 
  Writeln('The 100,000th Brazilian number: ', Num);
  readln;
end.
 
 