fix #2872
This commit is contained in:
parent
80904b2646
commit
08b1cfa442
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "9";
|
||||
public const string Build = "0";
|
||||
public const string Revision = "3351";
|
||||
public const string Revision = "3357";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%MINOR%=9
|
||||
%REVISION%=3351
|
||||
%REVISION%=3357
|
||||
%COREVERSION%=0
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.9.0.3351
|
||||
3.9.0.3357
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.9.0.3351'
|
||||
!define VERSION '3.9.0.3357'
|
||||
|
|
|
|||
|
|
@ -1,49 +1,59 @@
|
|||
/// Учебный модуль, реализующий базовые алгоритмы информатики.
|
||||
/// Учебный модуль, реализующий базовые алгоритмы информатики (09.10.2023)
|
||||
unit School;
|
||||
|
||||
interface
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления
|
||||
function Bin(Число: int64): string;
|
||||
function Bin(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления
|
||||
function Bin(Число: BigInteger): string;
|
||||
function Bin(number: BigInteger): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления с форматированием.
|
||||
/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна
|
||||
/// split - разделитель байтов, можено задать пустое значение ''
|
||||
function BinFormat(number: BigInteger; bytes: integer := 0; split: string := ' '): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления с форматированием.
|
||||
/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна
|
||||
/// split - разделитель байтов, можено задать пустое значение ''
|
||||
function BinFormat(number: int64; bytes: integer := 0; split: string := ' '): string;
|
||||
|
||||
/// Перевод десятичного числа в восьмеричную систему счисления
|
||||
function Oct(Число: int64): string;
|
||||
function Oct(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в восьмеричную систему счисления
|
||||
function Oct(Число: BigInteger): string;
|
||||
function Oct(number: BigInteger): string;
|
||||
|
||||
/// Перевод десятичного числа в шестнадцатиричную систему счисления
|
||||
function Hex(Число: int64): string;
|
||||
function Hex(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в шестнадцатиричную систему счисления
|
||||
function Hex(Число: BigInteger): string;
|
||||
function Hex(number: BigInteger): string;
|
||||
|
||||
/// Перевод из системы по основанию base [2..36] в десятичную
|
||||
function Dec(СтроковоеПредставление: string; Основание: integer): int64;
|
||||
function Dec(str: string; base: integer): int64;
|
||||
|
||||
/// Перевод из системы по основанию base [2..36] в десятичную
|
||||
function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger;
|
||||
function DecBig(str: string; base: integer): BigInteger;
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Число: BigInteger; Основание: integer): string;
|
||||
function ToBase(number: BigInteger; base: integer): string;
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(СтроковоеПредставление: string; Основание: integer): string;
|
||||
function ToBase(str: string; base: integer): string;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of int64): (int64, int64);
|
||||
function MinMax(seq: sequence of int64): (int64, int64);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of integer): (integer, integer);
|
||||
function MinMax(seq: sequence of integer): (integer, integer);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of real): (real, real);
|
||||
function MinMax(seq: sequence of real): (real, real);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
|
||||
/// Возвращает НОД пары чисел
|
||||
function НОД(a, b: int64): int64;
|
||||
|
|
@ -140,7 +150,7 @@ function TrueTable(f: function(a, b, c, d, e: boolean): boolean):
|
|||
procedure TrueTablePrint(a: array[,] of boolean; f: integer := 2; s: string := 'abcde');
|
||||
|
||||
/// Заменяет последнее вхождение подстроки в строку
|
||||
procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string);
|
||||
procedure ReplaceLast(var s: string; source, target: string);
|
||||
|
||||
/// Множественная замена символов в строке s
|
||||
/// Каждый символ source[i] заменяется во всей строке s символом target[i]
|
||||
|
|
@ -170,249 +180,263 @@ var
|
|||
|
||||
{$region Bin}
|
||||
|
||||
function Bin(Число: int64): string;
|
||||
function Bin(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 2 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += Число mod 2;
|
||||
Число := Число div 2
|
||||
Result += number mod 2;
|
||||
number := number div 2
|
||||
end;
|
||||
Result += Число;
|
||||
Result += number;
|
||||
Result := Result.Inverse
|
||||
end;
|
||||
|
||||
function Bin(Число: BigInteger): string;
|
||||
function Bin(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 2 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += byte(Число mod 2);
|
||||
Число := Число div 2
|
||||
Result += byte(number mod 2);
|
||||
number := number div 2
|
||||
end;
|
||||
Result += byte(Число);
|
||||
Result += byte(number);
|
||||
Result := Result.Inverse
|
||||
end;
|
||||
|
||||
function BinFormat(number: BigInteger; bytes: integer; split: string): string;
|
||||
begin
|
||||
if number < 0 then number := -number;
|
||||
var a := number = 0 ? |byte(0)| : number.ToByteArray;
|
||||
var len := a.Length;
|
||||
if (number > 0) and (a[^1] = 0) then Dec(len);
|
||||
SetLength(a, Max(bytes, len));
|
||||
Result := a.Reverse.Select(t -> (Convert.ToString(t, 2)).PadLeft(8, '0')).JoinToString(split)
|
||||
end;
|
||||
|
||||
function BinFormat(number: int64; bytes: integer; split: string): string :=
|
||||
BinFormat(BigInteger(number), bytes, split);
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region Oct}
|
||||
|
||||
function Oct(Число: int64): string;
|
||||
function Oct(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 8 do
|
||||
while number >= 8 do
|
||||
begin
|
||||
Result += Число mod 8;
|
||||
Число := Число div 8
|
||||
Result += number mod 8;
|
||||
number := number div 8
|
||||
end;
|
||||
Result += Число;
|
||||
Result := Result.Inverse
|
||||
Result += number;
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
function Oct(Число: BigInteger): string;
|
||||
function Oct(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 8 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += byte(Число mod 8);
|
||||
Число := Число div 8
|
||||
Result += byte(number mod 8);
|
||||
number := number div 8
|
||||
end;
|
||||
Result += byte(Число);
|
||||
Result := Result.Inverse
|
||||
Result += byte(number);
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region Hex}
|
||||
function Hex(Число: int64): string;
|
||||
|
||||
function Hex(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
var ШестнадцатиричныеЦифры := '0123456789ABCDEF';
|
||||
if number < 0 then number := -number;
|
||||
var hex_nums := '0123456789ABCDEF';
|
||||
Result := '';
|
||||
while Число >= 16 do
|
||||
while number >= 16 do
|
||||
begin
|
||||
Result += ШестнадцатиричныеЦифры[Число mod 16 + 1];
|
||||
Число := Число div 16
|
||||
Result += hex_nums[number mod 16 + 1];
|
||||
number := number div 16
|
||||
end;
|
||||
Result += ШестнадцатиричныеЦифры[Число + 1];
|
||||
Result := Result.Inverse
|
||||
Result += hex_nums[number + 1];
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
function Hex(Число: BigInteger): string;
|
||||
function Hex(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
var ШестнадцатиричныеЦифры := '0123456789ABCDEF';
|
||||
if number < 0 then number := -number;
|
||||
var hex_nums := '0123456789ABCDEF';
|
||||
Result := '';
|
||||
while Число >= 16 do
|
||||
while number >= 16 do
|
||||
begin
|
||||
Result += ШестнадцатиричныеЦифры[byte(Число mod 16) + 1];
|
||||
Число := Число div 16
|
||||
Result += hex_nums[byte(number mod 16 + 1)];
|
||||
number := number div 16
|
||||
end;
|
||||
Result += ШестнадцатиричныеЦифры[byte(Число) + 1];
|
||||
Result := Result.Inverse
|
||||
Result += hex_nums[byte(number + 1)];
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
const
|
||||
ДопустимыеСимволы = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
valid_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
{$region Dec}
|
||||
|
||||
function Dec(СтроковоеПредставление: string; Основание: integer): int64;
|
||||
function Dec(str: string; base: integer): int64;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
СтроковоеПредставление := СтроковоеПредставление.ToUpper;
|
||||
var НедопустимыеСимволы :=
|
||||
СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString;
|
||||
if НедопустимыеСимволы.Length > 0 then
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
str := str.ToUpper;
|
||||
var invalid_chars :=
|
||||
str.Except(valid_chars[:base + 1]).JoinToString;
|
||||
if invalid_chars.Length > 0 then
|
||||
raise new School_BadCharInString
|
||||
($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"');
|
||||
var ВесРазряда := 1bi;
|
||||
var Результат := 0bi;
|
||||
foreach var Символ in СтроковоеПредставление.Reverse do
|
||||
($'ToDecimal: Недопустимые символы "{invalid_chars}"');
|
||||
var rank_weight := 1bi;
|
||||
var res := 0bi;
|
||||
foreach var char in str.Reverse do
|
||||
begin
|
||||
var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1;
|
||||
Результат += ВесРазряда * ЗначениеРазряда;
|
||||
ВесРазряда *= Основание
|
||||
var rank_value := Pos(char, valid_chars) - 1;
|
||||
res += rank_weight * rank_value;
|
||||
rank_weight *= base
|
||||
end;
|
||||
Result := int64(Результат)
|
||||
Result := int64(res)
|
||||
end;
|
||||
|
||||
function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger;
|
||||
function DecBig(str: string; base: integer): BigInteger;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
СтроковоеПредставление := СтроковоеПредставление.ToUpper;
|
||||
var НедопустимыеСимволы :=
|
||||
СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString;
|
||||
if НедопустимыеСимволы.Length > 0 then
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
str := str.ToUpper;
|
||||
var invalid_chars :=
|
||||
str.Except(valid_chars[:base + 1]).JoinToString;
|
||||
if invalid_chars.Length > 0 then
|
||||
raise new School_BadCharInString
|
||||
($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"');
|
||||
var ВесРазряда := 1bi;
|
||||
($'ToDecimal: Недопустимые символы "{invalid_chars}"');
|
||||
var rank_weight := 1bi;
|
||||
Result := 0bi;
|
||||
foreach var Символ in СтроковоеПредставление.Reverse do
|
||||
foreach var char in str.Reverse do
|
||||
begin
|
||||
var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1;
|
||||
Result += ВесРазряда * ЗначениеРазряда;
|
||||
ВесРазряда *= Основание
|
||||
var rank_value := Pos(char, valid_chars) - 1;
|
||||
Result += rank_weight * rank_value;
|
||||
rank_weight *= base
|
||||
end
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region ToBase}
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Число: BigInteger; Основание: integer): string;
|
||||
function ToBase(number: BigInteger; base: integer): string;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
var СтроковоеПредставление := new System.Text.StringBuilder('');
|
||||
while Число > 0 do
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
var sb := new System.Text.StringBuilder('');
|
||||
while number > 0 do
|
||||
begin
|
||||
СтроковоеПредставление.Insert(0, ДопустимыеСимволы[integer(Число mod Основание) + 1]);
|
||||
Число := Число div Основание
|
||||
sb.Insert(0, valid_chars[integer(number mod base) + 1]);
|
||||
number := number div base
|
||||
end;
|
||||
Result := if СтроковоеПредставление.Length = 0 then '0'
|
||||
else СтроковоеПредставление.ToString
|
||||
Result := if sb.Length = 0 then '0'
|
||||
else sb.ToString
|
||||
end;
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Self: BigInteger; Основание: integer): string; extensionmethod :=
|
||||
ToBase(Self, Основание);
|
||||
function ToBase(Self: BigInteger; base: integer): string; extensionmethod :=
|
||||
ToBase(Self, base);
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(СтроковоеПредставление: string; Основание: integer): string;
|
||||
function ToBase(str: string; base: integer): string;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
var Число: BigInteger;
|
||||
if BigInteger.TryParse(СтроковоеПредставление, Число) then
|
||||
Result := ToBase(Число, Основание)
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
var number: BigInteger;
|
||||
if BigInteger.TryParse(str, number) then
|
||||
Result := ToBase(number, base)
|
||||
end;
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(Self: string; Основание: integer): string; extensionmethod :=
|
||||
ToBase(Self, Основание);
|
||||
function ToBase(Self: string; base: integer): string; extensionmethod :=
|
||||
ToBase(Self, base);
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region MinMax}
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of int64): (int64, int64);
|
||||
function MinMax(seq: sequence of int64): (int64, int64);
|
||||
begin
|
||||
var min := int64.MaxValue;
|
||||
var max := int64.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of integer): (integer, integer);
|
||||
function MinMax(seq: sequence of integer): (integer, integer);
|
||||
begin
|
||||
var min := integer.MaxValue;
|
||||
var max := integer.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности s
|
||||
function MinMax(Последовательность: sequence of real): (real, real);
|
||||
function MinMax(seq: sequence of real): (real, real);
|
||||
begin
|
||||
var min := real.MaxValue;
|
||||
var max := real.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
var max := -real.MaxValue;
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности s
|
||||
function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
begin
|
||||
var min, max: BigInteger;
|
||||
var ЭтоПервыйЭлемент := True;
|
||||
foreach var Элемент in Последовательность do
|
||||
if ЭтоПервыйЭлемент then
|
||||
var is_first := True;
|
||||
foreach var elem in seq do
|
||||
if is_first then
|
||||
begin
|
||||
min := Элемент;
|
||||
max := Элемент;
|
||||
ЭтоПервыйЭлемент := False
|
||||
(min, max) := (elem, elem);
|
||||
is_first := False
|
||||
end
|
||||
else
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
end;
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
|
|
@ -574,10 +598,10 @@ begin
|
|||
else
|
||||
begin
|
||||
Result := True;
|
||||
foreach var Простое in LPrimes do
|
||||
if Sqr(Простое) > Self then
|
||||
foreach var prime in LPrimes do
|
||||
if Sqr(prime) > Self then
|
||||
break
|
||||
else if Self mod Простое = 0 then
|
||||
else if Self mod prime = 0 then
|
||||
begin
|
||||
Result := False;
|
||||
break
|
||||
|
|
@ -931,13 +955,13 @@ end;
|
|||
{$region String}
|
||||
|
||||
/// Заменяет последнее вхождение подстроки в строку
|
||||
procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string);
|
||||
procedure ReplaceLast(var s: string; source, target: string);
|
||||
begin
|
||||
var Позиция := LastPos(ЧтоЗаменить, Строка);
|
||||
if Позиция > 0 then
|
||||
var position := LastPos(source, s);
|
||||
if position > 0 then
|
||||
begin
|
||||
Delete(Строка, Позиция, ЧтоЗаменить.Length);
|
||||
Insert(ЧемЗаменить, Строка, Позиция)
|
||||
Delete(s, position, source.Length);
|
||||
Insert(target, s, position)
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
|
|||
3
TestSuite/SingleReal.pas
Normal file
3
TestSuite/SingleReal.pas
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
begin
|
||||
Assert(Arr(1.0,2.0).Sum(x -> x*x).GetType = typeof(real))
|
||||
end.
|
||||
11
TestSuite/check_sequence.pas
Normal file
11
TestSuite/check_sequence.pas
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
procedure CheckOutputSeq(a: sequence of integer);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure CheckOutputSeq(a: sequence of object);
|
||||
begin
|
||||
end;
|
||||
|
||||
begin
|
||||
CheckOutputSeq(Arr(1,2,3));
|
||||
end.
|
||||
|
|
@ -575,8 +575,8 @@ namespace PascalABCCompiler.TreeRealization
|
|||
// Но без этой строчки не работает преобразование sequence of Student к sequence of Person и sequence of object
|
||||
// SSM 19/07/23 - снова раскомментировал - теперь не работало
|
||||
// CheckOutputSeq(a); в Tasks где var a: array of char
|
||||
if (tnode.IsInterface)
|
||||
ImplementingInterfaces.Add(tnode);
|
||||
//if (tnode.IsInterface) // SSM закомментировал опять 17.09.23 - single - неточные вычисления!
|
||||
// ImplementingInterfaces.Add(tnode);
|
||||
foreach (var interf in ImplementingInterfaces)
|
||||
{
|
||||
var ctn = interf as compiled_type_node;
|
||||
|
|
@ -809,6 +809,18 @@ namespace PascalABCCompiler.TreeRealization
|
|||
public static type_compare compare_types(type_node left, type_node right)
|
||||
{
|
||||
type_compare ret = get_table_type_compare(left, right);
|
||||
// SSM 18.09.23 исправление #2872 (частное!!! только первый параметр!)
|
||||
var ctnl = left as compiled_type_node;
|
||||
var ctnr = right as compiled_type_node;
|
||||
if (ctnl != null && ctnr != null && ctnl.original_generic == ctnr.original_generic
|
||||
&& ctnl.compiled_type.IsInterface && ctnl.generic_params != null && ctnl.generic_params.Count == 1)
|
||||
{
|
||||
var interf_compiled_type = (ctnr.original_generic as compiled_type_node).compiled_type;
|
||||
if ((interf_compiled_type.GetGenericArguments()[0].GenericParameterAttributes & System.Reflection.GenericParameterAttributes.Covariant) != 0)
|
||||
return compare_types(ctnl.generic_params[0], ctnr.generic_params[0]);
|
||||
}
|
||||
// IEnumerable<object> д.б. < IEnumerable<integer>
|
||||
// Проверить, что оба - IEnumerable. И если object < integer, то вернуть type_compare.less_type
|
||||
if (ret != type_compare.non_comparable_type)
|
||||
{
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -1,49 +1,59 @@
|
|||
/// Учебный модуль, реализующий базовые алгоритмы информатики.
|
||||
/// Учебный модуль, реализующий базовые алгоритмы информатики (09.10.2023)
|
||||
unit School;
|
||||
|
||||
interface
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления
|
||||
function Bin(Число: int64): string;
|
||||
function Bin(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления
|
||||
function Bin(Число: BigInteger): string;
|
||||
function Bin(number: BigInteger): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления с форматированием.
|
||||
/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна
|
||||
/// split - разделитель байтов, можено задать пустое значение ''
|
||||
function BinFormat(number: BigInteger; bytes: integer := 0; split: string := ' '): string;
|
||||
|
||||
/// Перевод десятичного числа в двоичную систему счисления с форматированием.
|
||||
/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна
|
||||
/// split - разделитель байтов, можено задать пустое значение ''
|
||||
function BinFormat(number: int64; bytes: integer := 0; split: string := ' '): string;
|
||||
|
||||
/// Перевод десятичного числа в восьмеричную систему счисления
|
||||
function Oct(Число: int64): string;
|
||||
function Oct(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в восьмеричную систему счисления
|
||||
function Oct(Число: BigInteger): string;
|
||||
function Oct(number: BigInteger): string;
|
||||
|
||||
/// Перевод десятичного числа в шестнадцатиричную систему счисления
|
||||
function Hex(Число: int64): string;
|
||||
function Hex(number: int64): string;
|
||||
|
||||
/// Перевод десятичного числа в шестнадцатиричную систему счисления
|
||||
function Hex(Число: BigInteger): string;
|
||||
function Hex(number: BigInteger): string;
|
||||
|
||||
/// Перевод из системы по основанию base [2..36] в десятичную
|
||||
function Dec(СтроковоеПредставление: string; Основание: integer): int64;
|
||||
function Dec(str: string; base: integer): int64;
|
||||
|
||||
/// Перевод из системы по основанию base [2..36] в десятичную
|
||||
function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger;
|
||||
function DecBig(str: string; base: integer): BigInteger;
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Число: BigInteger; Основание: integer): string;
|
||||
function ToBase(number: BigInteger; base: integer): string;
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(СтроковоеПредставление: string; Основание: integer): string;
|
||||
function ToBase(str: string; base: integer): string;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of int64): (int64, int64);
|
||||
function MinMax(seq: sequence of int64): (int64, int64);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of integer): (integer, integer);
|
||||
function MinMax(seq: sequence of integer): (integer, integer);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of real): (real, real);
|
||||
function MinMax(seq: sequence of real): (real, real);
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
|
||||
/// Возвращает НОД пары чисел
|
||||
function НОД(a, b: int64): int64;
|
||||
|
|
@ -140,7 +150,7 @@ function TrueTable(f: function(a, b, c, d, e: boolean): boolean):
|
|||
procedure TrueTablePrint(a: array[,] of boolean; f: integer := 2; s: string := 'abcde');
|
||||
|
||||
/// Заменяет последнее вхождение подстроки в строку
|
||||
procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string);
|
||||
procedure ReplaceLast(var s: string; source, target: string);
|
||||
|
||||
/// Множественная замена символов в строке s
|
||||
/// Каждый символ source[i] заменяется во всей строке s символом target[i]
|
||||
|
|
@ -170,249 +180,263 @@ var
|
|||
|
||||
{$region Bin}
|
||||
|
||||
function Bin(Число: int64): string;
|
||||
function Bin(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 2 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += Число mod 2;
|
||||
Число := Число div 2
|
||||
Result += number mod 2;
|
||||
number := number div 2
|
||||
end;
|
||||
Result += Число;
|
||||
Result += number;
|
||||
Result := Result.Inverse
|
||||
end;
|
||||
|
||||
function Bin(Число: BigInteger): string;
|
||||
function Bin(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 2 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += byte(Число mod 2);
|
||||
Число := Число div 2
|
||||
Result += byte(number mod 2);
|
||||
number := number div 2
|
||||
end;
|
||||
Result += byte(Число);
|
||||
Result += byte(number);
|
||||
Result := Result.Inverse
|
||||
end;
|
||||
|
||||
function BinFormat(number: BigInteger; bytes: integer; split: string): string;
|
||||
begin
|
||||
if number < 0 then number := -number;
|
||||
var a := number = 0 ? |byte(0)| : number.ToByteArray;
|
||||
var len := a.Length;
|
||||
if (number > 0) and (a[^1] = 0) then Dec(len);
|
||||
SetLength(a, Max(bytes, len));
|
||||
Result := a.Reverse.Select(t -> (Convert.ToString(t, 2)).PadLeft(8, '0')).JoinToString(split)
|
||||
end;
|
||||
|
||||
function BinFormat(number: int64; bytes: integer; split: string): string :=
|
||||
BinFormat(BigInteger(number), bytes, split);
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region Oct}
|
||||
|
||||
function Oct(Число: int64): string;
|
||||
function Oct(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 8 do
|
||||
while number >= 8 do
|
||||
begin
|
||||
Result += Число mod 8;
|
||||
Число := Число div 8
|
||||
Result += number mod 8;
|
||||
number := number div 8
|
||||
end;
|
||||
Result += Число;
|
||||
Result := Result.Inverse
|
||||
Result += number;
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
function Oct(Число: BigInteger): string;
|
||||
function Oct(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
if number < 0 then number := -number;
|
||||
Result := '';
|
||||
while Число >= 8 do
|
||||
while number >= 2 do
|
||||
begin
|
||||
Result += byte(Число mod 8);
|
||||
Число := Число div 8
|
||||
Result += byte(number mod 8);
|
||||
number := number div 8
|
||||
end;
|
||||
Result += byte(Число);
|
||||
Result := Result.Inverse
|
||||
Result += byte(number);
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region Hex}
|
||||
function Hex(Число: int64): string;
|
||||
|
||||
function Hex(number: int64): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
var ШестнадцатиричныеЦифры := '0123456789ABCDEF';
|
||||
if number < 0 then number := -number;
|
||||
var hex_nums := '0123456789ABCDEF';
|
||||
Result := '';
|
||||
while Число >= 16 do
|
||||
while number >= 16 do
|
||||
begin
|
||||
Result += ШестнадцатиричныеЦифры[Число mod 16 + 1];
|
||||
Число := Число div 16
|
||||
Result += hex_nums[number mod 16 + 1];
|
||||
number := number div 16
|
||||
end;
|
||||
Result += ШестнадцатиричныеЦифры[Число + 1];
|
||||
Result := Result.Inverse
|
||||
Result += hex_nums[number + 1];
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
function Hex(Число: BigInteger): string;
|
||||
function Hex(number: BigInteger): string;
|
||||
begin
|
||||
Число := Abs(Число);
|
||||
var ШестнадцатиричныеЦифры := '0123456789ABCDEF';
|
||||
if number < 0 then number := -number;
|
||||
var hex_nums := '0123456789ABCDEF';
|
||||
Result := '';
|
||||
while Число >= 16 do
|
||||
while number >= 16 do
|
||||
begin
|
||||
Result += ШестнадцатиричныеЦифры[byte(Число mod 16) + 1];
|
||||
Число := Число div 16
|
||||
Result += hex_nums[byte(number mod 16 + 1)];
|
||||
number := number div 16
|
||||
end;
|
||||
Result += ШестнадцатиричныеЦифры[byte(Число) + 1];
|
||||
Result := Result.Inverse
|
||||
Result += hex_nums[byte(number + 1)];
|
||||
Result := Result.Inverse;
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
const
|
||||
ДопустимыеСимволы = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
valid_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
{$region Dec}
|
||||
|
||||
function Dec(СтроковоеПредставление: string; Основание: integer): int64;
|
||||
function Dec(str: string; base: integer): int64;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
СтроковоеПредставление := СтроковоеПредставление.ToUpper;
|
||||
var НедопустимыеСимволы :=
|
||||
СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString;
|
||||
if НедопустимыеСимволы.Length > 0 then
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
str := str.ToUpper;
|
||||
var invalid_chars :=
|
||||
str.Except(valid_chars[:base + 1]).JoinToString;
|
||||
if invalid_chars.Length > 0 then
|
||||
raise new School_BadCharInString
|
||||
($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"');
|
||||
var ВесРазряда := 1bi;
|
||||
var Результат := 0bi;
|
||||
foreach var Символ in СтроковоеПредставление.Reverse do
|
||||
($'ToDecimal: Недопустимые символы "{invalid_chars}"');
|
||||
var rank_weight := 1bi;
|
||||
var res := 0bi;
|
||||
foreach var char in str.Reverse do
|
||||
begin
|
||||
var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1;
|
||||
Результат += ВесРазряда * ЗначениеРазряда;
|
||||
ВесРазряда *= Основание
|
||||
var rank_value := Pos(char, valid_chars) - 1;
|
||||
res += rank_weight * rank_value;
|
||||
rank_weight *= base
|
||||
end;
|
||||
Result := int64(Результат)
|
||||
Result := int64(res)
|
||||
end;
|
||||
|
||||
function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger;
|
||||
function DecBig(str: string; base: integer): BigInteger;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
СтроковоеПредставление := СтроковоеПредставление.ToUpper;
|
||||
var НедопустимыеСимволы :=
|
||||
СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString;
|
||||
if НедопустимыеСимволы.Length > 0 then
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
str := str.ToUpper;
|
||||
var invalid_chars :=
|
||||
str.Except(valid_chars[:base + 1]).JoinToString;
|
||||
if invalid_chars.Length > 0 then
|
||||
raise new School_BadCharInString
|
||||
($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"');
|
||||
var ВесРазряда := 1bi;
|
||||
($'ToDecimal: Недопустимые символы "{invalid_chars}"');
|
||||
var rank_weight := 1bi;
|
||||
Result := 0bi;
|
||||
foreach var Символ in СтроковоеПредставление.Reverse do
|
||||
foreach var char in str.Reverse do
|
||||
begin
|
||||
var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1;
|
||||
Result += ВесРазряда * ЗначениеРазряда;
|
||||
ВесРазряда *= Основание
|
||||
var rank_value := Pos(char, valid_chars) - 1;
|
||||
Result += rank_weight * rank_value;
|
||||
rank_weight *= base
|
||||
end
|
||||
end;
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region ToBase}
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Число: BigInteger; Основание: integer): string;
|
||||
function ToBase(number: BigInteger; base: integer): string;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
var СтроковоеПредставление := new System.Text.StringBuilder('');
|
||||
while Число > 0 do
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
var sb := new System.Text.StringBuilder('');
|
||||
while number > 0 do
|
||||
begin
|
||||
СтроковоеПредставление.Insert(0, ДопустимыеСимволы[integer(Число mod Основание) + 1]);
|
||||
Число := Число div Основание
|
||||
sb.Insert(0, valid_chars[integer(number mod base) + 1]);
|
||||
number := number div base
|
||||
end;
|
||||
Result := if СтроковоеПредставление.Length = 0 then '0'
|
||||
else СтроковоеПредставление.ToString
|
||||
Result := if sb.Length = 0 then '0'
|
||||
else sb.ToString
|
||||
end;
|
||||
|
||||
/// Перевод BigInteger в систему счисления по основанию base (2..36)
|
||||
function ToBase(Self: BigInteger; Основание: integer): string; extensionmethod :=
|
||||
ToBase(Self, Основание);
|
||||
function ToBase(Self: BigInteger; base: integer): string; extensionmethod :=
|
||||
ToBase(Self, base);
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(СтроковоеПредставление: string; Основание: integer): string;
|
||||
function ToBase(str: string; base: integer): string;
|
||||
begin
|
||||
if not (Основание in 2..36) then
|
||||
if not (base in 2..36) then
|
||||
raise new School_InvalidBase
|
||||
($'ToDecimal: Недопустимое основание {Основание}');
|
||||
var Число: BigInteger;
|
||||
if BigInteger.TryParse(СтроковоеПредставление, Число) then
|
||||
Result := ToBase(Число, Основание)
|
||||
($'ToDecimal: Недопустимое основание {base}');
|
||||
var number: BigInteger;
|
||||
if BigInteger.TryParse(str, number) then
|
||||
Result := ToBase(number, base)
|
||||
end;
|
||||
|
||||
/// Перевод десятичного числа в систему счисления по основанию base (2..36)
|
||||
function ToBase(Self: string; Основание: integer): string; extensionmethod :=
|
||||
ToBase(Self, Основание);
|
||||
function ToBase(Self: string; base: integer): string; extensionmethod :=
|
||||
ToBase(Self, base);
|
||||
|
||||
{$endregion}
|
||||
|
||||
{$region MinMax}
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of int64): (int64, int64);
|
||||
function MinMax(seq: sequence of int64): (int64, int64);
|
||||
begin
|
||||
var min := int64.MaxValue;
|
||||
var max := int64.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности
|
||||
function MinMax(Последовательность: sequence of integer): (integer, integer);
|
||||
function MinMax(seq: sequence of integer): (integer, integer);
|
||||
begin
|
||||
var min := integer.MaxValue;
|
||||
var max := integer.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности s
|
||||
function MinMax(Последовательность: sequence of real): (real, real);
|
||||
function MinMax(seq: sequence of real): (real, real);
|
||||
begin
|
||||
var min := real.MaxValue;
|
||||
var max := real.MinValue;
|
||||
foreach var Элемент in Последовательность do
|
||||
var max := -real.MaxValue;
|
||||
foreach var elem in seq do
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
/// Возвращает кортеж из минимума и максимума последовательности s
|
||||
function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger);
|
||||
begin
|
||||
var min, max: BigInteger;
|
||||
var ЭтоПервыйЭлемент := True;
|
||||
foreach var Элемент in Последовательность do
|
||||
if ЭтоПервыйЭлемент then
|
||||
var is_first := True;
|
||||
foreach var elem in seq do
|
||||
if is_first then
|
||||
begin
|
||||
min := Элемент;
|
||||
max := Элемент;
|
||||
ЭтоПервыйЭлемент := False
|
||||
(min, max) := (elem, elem);
|
||||
is_first := False
|
||||
end
|
||||
else
|
||||
begin
|
||||
if Элемент < min then
|
||||
min := Элемент;
|
||||
if Элемент > max then
|
||||
max := Элемент
|
||||
end;
|
||||
if elem < min then
|
||||
min := elem;
|
||||
if elem > max then
|
||||
max := elem
|
||||
end;
|
||||
Result := (min, max)
|
||||
end;
|
||||
|
||||
|
|
@ -574,10 +598,10 @@ begin
|
|||
else
|
||||
begin
|
||||
Result := True;
|
||||
foreach var Простое in LPrimes do
|
||||
if Sqr(Простое) > Self then
|
||||
foreach var prime in LPrimes do
|
||||
if Sqr(prime) > Self then
|
||||
break
|
||||
else if Self mod Простое = 0 then
|
||||
else if Self mod prime = 0 then
|
||||
begin
|
||||
Result := False;
|
||||
break
|
||||
|
|
@ -931,13 +955,13 @@ end;
|
|||
{$region String}
|
||||
|
||||
/// Заменяет последнее вхождение подстроки в строку
|
||||
procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string);
|
||||
procedure ReplaceLast(var s: string; source, target: string);
|
||||
begin
|
||||
var Позиция := LastPos(ЧтоЗаменить, Строка);
|
||||
if Позиция > 0 then
|
||||
var position := LastPos(source, s);
|
||||
if position > 0 then
|
||||
begin
|
||||
Delete(Строка, Позиция, ЧтоЗаменить.Length);
|
||||
Insert(ЧемЗаменить, Строка, Позиция)
|
||||
Delete(s, position, source.Length);
|
||||
Insert(target, s, position)
|
||||
end
|
||||
end;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue