{$HiddenIdents} unit SPythonSystem; // В SPython данной версии нет возможности использовать пространства имен // {$reference '%GAC%\System.dll'} // {$reference '%GAC%\mscorlib.dll'} // {$reference '%GAC%\System.Core.dll'} // {$reference '%GAC%\System.Numerics.dll'} interface // uses PABCSystem; // Basic IO methods function input(): string; function input(s: string): string; ///- type kwargs_gen = class public !kwargs: Dictionary := new Dictionary(); constructor Create( keys: array of string; params values: array of T ); begin for var i := 0 to keys.count() - 1 do !kwargs[keys[i]] := values[i]; end; constructor Create( keys: array of char; params values: array of T ); begin for var i := 0 to keys.count() - 1 do !kwargs[keys[i]] := values[i]; end; constructor Create(); begin end; end; function all(s: sequence of boolean): boolean; function any(s: sequence of boolean): boolean; function enumerate(s: sequence of T; start: integer := 0): sequence of (integer,T); function filter(cond: T -> boolean; s: sequence of T): sequence of T; function sorted(s: sequence of T; reverse: boolean := false): sequence of T; function sorted(s: sequence of T; key: T -> T1; reverse: boolean := false): sequence of T; function int(val: string): integer; function int(val: real): integer; function round(val: real): integer; function split(s: string): sequence of string; function get_keys(dct: Dictionary): sequence of K; function get_values(dct: Dictionary): sequence of V; function &type(obj: object): string; //function int(val: string): integer; function int(b: boolean): integer; function str(val: object): string; function float(val: string): real; function float(x: integer): real; // Basic sequence functions function range(s: integer; e: integer; step: integer): sequence of integer; function range(e: integer): sequence of integer; function range(s: integer; e: integer): sequence of integer; function !format(obj: object; fmt: string): string; function !format(i: integer; fmt: string): string; function !format(val: real; fmt: string): string; //function all(seq: sequence of T): boolean; //function any(seq: sequence of T): boolean; // Standard Math functions function abs(x: integer): integer; function abs(x: real): real; // function floor(x: real): real; type list = class(IEnumerable) private wrappee : PABCSystem.List; constructor Create(l : PABCSystem.List) := wrappee := l; function GetItem(ind : integer) : T := wrappee[ind]; procedure SetItem(ind : integer; newItem : T) := wrappee[ind] := newItem; public static function operator implicit(l : PABCSystem.List) : list := new list(l); constructor Create() := wrappee := new PABCSystem.List(); constructor Create(capacity : integer) := wrappee := new PABCSystem.List(capacity); constructor Create(collection : sequence of T) := wrappee := new PABCSystem.List(collection); property ByIndex[ind : integer] : T read GetItem write SetItem; default; ///-- property !count : integer read wrappee.Count; procedure append(item : T) := wrappee.Add(item); procedure extend(seq : sequence of T) := wrappee.AddRange(seq); procedure clear() := wrappee.Clear(); procedure insert(index : integer; item : T) := wrappee.Insert(index, item); procedure remove(item : T); begin if not wrappee.Remove(item) then raise new System.ArgumentException($'ValueError: {item} is not in list'); end; function pop() : T; begin var lastIndex := wrappee.Count - 1; Result := wrappee[lastIndex]; wrappee.RemoveAt(lastIndex); end; function pop(index : integer) : T; begin Result := wrappee[index]; wrappee.RemoveAt(index); end; function index(item : T) : integer := index(item, 0, wrappee.Count); function index(item : T; start : integer) : integer := index(item, start, wrappee.Count); function index(item : T; start : integer; &end : integer) : integer; begin Result := wrappee.IndexOf(item, start, &end - start); if Result = -1 then raise new System.ArgumentException($'ValueError: {item} is not in list'); end; function count(item : T) : integer; begin var comparer := System.Collections.Generic.EqualityComparer&.Default; Result := 0; for var i := 0 to wrappee.Count - 1 do begin if comparer.Equals(wrappee[i], item) then Result += 1; end; end; procedure sort() := wrappee.Sort(); procedure sort(reverse : boolean) := wrappee.OrderByDescending(x -> x); procedure sort(key : T -> TKey) := wrappee.OrderBy(key); procedure sort(key : T -> TKey; reverse : boolean) := wrappee.OrderByDescending(key); procedure reverse() := wrappee.Reverse(); function copy() : list := new list(wrappee.ToList()); function GetEnumerator() : IEnumerator := wrappee.GetEnumerator(); function System.Collections.IEnumerable.GetEnumerator() : System.Collections.IEnumerator := GetEnumerator(); end; type &set = record(IEnumerable) private wrappee : PABCSystem.HashSet; constructor Create(h : PABCSystem.HashSet) := wrappee := h; public constructor Create() := wrappee := new PABCSystem.HashSet(); constructor Create(collection : sequence of T) := wrappee := new PABCSystem.HashSet(collection); constructor Create(collection : sequence of T; comparer : PABCSystem.IEqualityComparer) := wrappee := new PABCSystem.HashSet(collection, comparer); constructor Create(comparer : PABCSystem.IEqualityComparer) := wrappee := new PABCSystem.HashSet(comparer); ///-- property !count : integer read wrappee.Count; procedure add(elem : T) := wrappee.Add(elem); procedure remove(elem : T); begin if not wrappee.Remove(elem) then raise new System.Collections.Generic.KeyNotFoundException('KeyError: ' + elem.ToString()); end; procedure discard(elem : T) := wrappee.Remove(elem); function pop() : T; begin if wrappee.Count = 0 then raise new System.Collections.Generic.KeyNotFoundException('KeyError: ''pop from an empty set'''); Result := wrappee.First(); wrappee.Remove(Result); end; procedure clear() := wrappee.Clear(); function copy() : &set := new &set(wrappee.ToHashSet()); static function operator in(elem: T; Self: &set): boolean; begin Result := Self.wrappee.Contains(elem); end; private function setOperation1(op : (HashSet, sequence of T) -> (); params others : array of sequence of T) : &set; begin Result.wrappee := wrappee.ToHashSet(); foreach var seq in others do op(Result.wrappee, seq); end; procedure setOperation2(op : (HashSet, sequence of T) -> (); params others : array of sequence of T); begin foreach var seq in others do op(wrappee, seq); end; public function intersection(params others : array of sequence of T) : &set := setOperation1((h1, h2) -> h1.IntersectWith(h2), others); function union(params others : array of sequence of T) : &set := setOperation1((h1, h2) -> h1.UnionWith(h2), others); function difference(params others : array of sequence of T) : &set := setOperation1((h1, h2) -> h1.ExceptWith(h2), others); function symmetric_difference(params others : array of sequence of T) : &set := setOperation1((h1, h2) -> h1.SymmetricExceptWith(h2), others); procedure update(params others : array of sequence of T) := setOperation2((h1, h2) -> h1.UnionWith(h2), others); procedure update(other : sequence of T) := wrappee.UnionWith(other); procedure intersection_update(params others : array of sequence of T) := setOperation2((h1, h2) -> h1.IntersectWith(h2), others); procedure intersection_update(other : sequence of T) := wrappee.IntersectWith(other); procedure difference_update(params others : array of sequence of T) := setOperation2((h1, h2) -> h1.ExceptWith(h2), others); procedure difference_update(other : sequence of T) := wrappee.ExceptWith(other); procedure symmetric_difference_update(params others : array of sequence of T) := setOperation2((h1, h2) -> h1.SymmetricExceptWith(h2), others); procedure symmetric_difference_update(other : sequence of T) := wrappee.SymmetricExceptWith(other); function isdisjoint(other : sequence of T) : boolean; function issubset(other : sequence of T) : boolean := wrappee.IsSubsetOf(other); function issuperset(other : sequence of T) : boolean := wrappee.IsSupersetOf(other); static function operator=(s1 : &set; s2 : &set) : boolean := s1.wrappee.SetEquals(s2.wrappee); static function operator<>(s1 : &set; s2 : &set) : boolean := not (s1 = s2); static function operator<=(s1 : &set; s2 : &set) : boolean := s1.issubset(s2); static function operator<(s1 : &set; s2 : &set) : boolean := (s1 <= s2) and (s1 <> s2); static function operator>=(s1 : &set; s2 : &set) : boolean := s1.issuperset(s2); static function operator>(s1 : &set; s2 : &set) : boolean := (s1 >= s2) and (s1 <> s2); static function operator or(s1 : &set; s2 : &set) : &set := s1.union(s2); ///- function !orEqual(other : &set) : &set; begin update(other); Result := Self; end; static function operator and(s1 : &set; s2 : &set) : &set := s1.intersection(s2); ///- function !andEqual(other : &set) : &set; begin intersection_update(other); Result := Self; end; static function operator-(s1 : &set; s2 : &set) : &set := s1.difference(s2); static function operator -=(var s1 : &set; s2 : &set) : &set; begin s1.difference_update(s2); end; static function operator xor(s1 : &set; s2 : &set) : &set := s1.symmetric_difference(s2); ///- function !xorEqual(other : &set) : &set; begin symmetric_difference_update(other); Result := Self; end; // static function operator:=(var s1: &set; s2: &set): &set; // begin // s1.wrappee := s2.wrappee.ToHashSet(); // end; static function operator implicit(s : HashSet) : &set := new &set(s); function GetEnumerator() : IEnumerator := wrappee.GetEnumerator(); function System.Collections.IEnumerable.GetEnumerator() : System.Collections.IEnumerator := GetEnumerator(); end; type dict = class(IEnumerable>) private wrappee : PABCSystem.Dictionary; constructor Create(d : PABCSystem.Dictionary) := wrappee := d; function GetValue(key : K) : V := wrappee[key]; procedure SetValue(key : K; val : V) := wrappee[key] := val; public constructor Create() := wrappee := new PABCSystem.Dictionary(); constructor Create(capacity : integer) := wrappee := new PABCSystem.Dictionary(capacity); constructor Create(comparer : PABCSystem.IEqualityComparer) := wrappee := new PABCSystem.Dictionary(comparer); constructor Create(capacity : integer; comparer : PABCSystem.IEqualityComparer) := wrappee := new PABCSystem.Dictionary(capacity, comparer); constructor Create(params pairs: array of (K, V)); begin wrappee := new PABCSystem.Dictionary(); for var i := 0 to pairs.Length - 1 do wrappee[pairs[i].Item1] := pairs[i].Item2; end; constructor Create(seqOfPairs : sequence of (K, V)); begin wrappee := new PABCSystem.Dictionary(); foreach var p in seqOfPairs do wrappee[p.Item1] := p.Item2; end; ///-- property !count : integer read wrappee.Count; property ByKey[key : K] : V read GetValue write SetValue; default; static function operator in(key: K; Self: dict): boolean; begin Result := Self.wrappee.ContainsKey(key); end; procedure clear() := wrappee.Clear(); function copy() : dict := new dict(new Dictionary(wrappee)); static function fromkeys(sq : sequence of K; val : V := default(V)) : dict; begin Result := new dict(); foreach var key in sq do Result[key] := val; end; function get(key : K; &default : V := default(V)) : V; begin var val : V; if wrappee.TryGetValue(key, val) then Result := val else Result := &default; end; function items() : sequence of KeyValuePair := wrappee; function keys() := wrappee.Keys; function pop(key : K) : V; begin Result := wrappee[key]; wrappee.Remove(key); end; function pop(key : K; &default : V) : V; begin var val : V; if wrappee.TryGetValue(key, val) then begin Result := val; wrappee.Remove(key); end else Result := &default; end; function popitem() : KeyValuePair; begin Result := wrappee.Last(); wrappee.Remove(Result.Key); end; function setdefault(key : K; &default : V := default(V)) : V; begin var val : V; if wrappee.TryGetValue(key, val) then Result := val else begin wrappee[key] := &default; Result := &default; end; end; procedure update(params pairs: array of (K, V)); begin for var i := 0 to pairs.Length - 1 do wrappee[pairs[i].Item1] := pairs[i].Item2; end; procedure update(seqOfPairs : sequence of (K, V)); begin foreach var p in seqOfPairs do wrappee[p.Item1] := p.Item2; end; function values() := wrappee.Values; static function operator or(d1 : dict; d2 : dict) : dict; begin Result := new dict(d1.wrappee); foreach var p in d2.wrappee do Result[p.Key] := p.Value; end; static function operator implicit(d : PABCSystem.Dictionary) : dict := new dict(d); function GetEnumerator() : IEnumerator> := wrappee.GetEnumerator(); function System.Collections.IEnumerable.GetEnumerator() : System.Collections.IEnumerator := GetEnumerator(); end; //Standard functions with Lists function len(lst: list): integer; function len(st: &set): integer; function len(dct: dict): integer; function len(arr: array of T): integer; function len(s: string): integer; // function &set(sq: sequence of T): &set; function sorted(lst: list): list; function sum(lst: sequence of integer): integer; function sum(lst: sequence of real): real; function !assign(var a: T; b: T): T; function !pow(x, n: integer): integer; function !pow(x, n: biginteger): biginteger; function !pow(x: integer; y: real): real; function !pow(x: real; y: real): real; function bigint(x: integer): biginteger; function !pow_recursion(x, n: integer): integer; function !pow_recursion(x, n: biginteger): biginteger; // TUPLES BEGIN function CreateTuple( v1: T1; v2: T2 ): System.Tuple; function CreateTuple( v1: T1; v2: T2; v3: T3 ): System.Tuple; function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4 ): System.Tuple; function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5 ): System.Tuple; function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6 ): System.Tuple; function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6; v7: T7 ): System.Tuple; // TUPLES END type biginteger = PABCSystem.BigInteger; tuple2 = System.Tuple; tuple3 = System.Tuple; tuple4 = System.Tuple; tuple5 = System.Tuple; tuple6 = System.Tuple; tuple7 = System.Tuple; empty_list = class class function operator implicit(x: empty_list): list; begin Result := new list(); end; end; empty_set = class class function operator implicit(x: empty_set): &set; begin Result := new &set(); end; end; empty_dict = class class function operator implicit(x: empty_dict): dict; begin Result := new dict(); end; end; function !empty_list(): empty_list; function !empty_dict(): empty_dict; implementation function input(): string; begin PABCSystem.Print(); Result := PABCSystem.ReadlnString(); end; function input(s: string): string; begin PABCSystem.Print(s); Result := PABCSystem.ReadlnString(); end; function enumerate(s: sequence of T; start: integer): sequence of (integer,T) := s.Numerate(start); function filter(cond: T -> boolean; s: sequence of T): sequence of T := s.Where(cond); function sorted(s: sequence of T; reverse: boolean): sequence of T := reverse ? s.OrderDescending : s.Order; function sorted(s: sequence of T; key: T -> T1; reverse: boolean): sequence of T := reverse ? s.OrderByDescending(key) : s.OrderBy(key); function int(val: string): integer := integer.Parse(val); function int(val: real): integer := round(val); function int(b: boolean): integer; begin if b then Result := 1 else Result := 0; end; function &type(obj: object): string; begin Result := TypeName(obj) .Replace('<', '[') .Replace('>', ']') .Replace('empty_list', 'list[anytype]') .Replace('empty_set', 'set[anytype]') .Replace('empty_dict', 'dict[anytype]') .Replace('integer', 'int') .Replace('string', 'str') .Replace('real', 'float') .Replace('boolean', 'bool') .Replace('System.Numerics.BigInteger', 'bigint'); end; function int(obj: object): integer := Convert.ToInt32(obj); function str(val: object): string := val.ToString(); function float(val: string): real := real.Parse(val); function float(x: integer): real := PABCSystem.Floor(x); function range(s: integer; e: integer; step: integer): sequence of integer; begin Result := PABCSystem.Range(s, e - PABCSystem.Sign(step), step); end; function range(s: integer; e: integer): sequence of integer; begin Result := PABCSystem.Range(s, e - 1); end; function range(e: integer): sequence of integer; begin Result := PABCSystem.Range(0, e - 1); end; //function all(seq: sequence of T): boolean := seq.All(x -> x); //function any(seq: sequence of T): boolean := seq.Any(x -> x); function abs(x: integer): integer := if x >= 0 then x else -x; function abs(x: real): real := PABCSystem.Abs(x); function len(lst: list): integer := lst.!count; function len(st: &set): integer := st.!count; function len(dct: dict): integer := dct.!count; function len(arr: array of T): integer := arr.Length; function len(s: string): integer := s.Length; function sorted(lst: list): list; begin var newList := lst.copy(); newList.sort(); Result := newList; end; function sum(lst: sequence of integer): integer := lst.sum(); function sum(lst: sequence of real): real := lst.sum(); function !assign(var a: T; b: T): T; begin a := b; Result := a; end; function !pow(x, n: biginteger): biginteger; begin if (n < 0) then raise new System.ArgumentException('возведение в степень не работает для целой отрицательной степени типа bigint.'); Result := !pow_recursion(x, n); end; function !pow_recursion(x, n: biginteger): biginteger; begin if (n = 0) then Result := 1 else begin Result := !pow_recursion(x, n div 2); Result *= Result; if ((n mod 2) = 1) then Result *= x; end; end; function !pow(x, n: integer): integer; begin if (n < 0) then raise new System.ArgumentException('возведение в степень не работает для целой отрицательной степени, используйте привидение к типу с плавающей точкой.'); Result := !pow_recursion(x, n); end; function !pow(x: integer; y: real): real := Power(x, y); function !pow(x: real; y: real): real := Power(x, y); function !pow_recursion(x, n: integer): integer; begin if (n = 0) then Result := 1 else begin Result := !pow_recursion(x, n div 2); Result *= Result; if ((n mod 2) = 1) then Result *= x; end; end; function bigint(x: integer): biginteger; begin Result := x; end; function &set.isdisjoint(other : sequence of T) : boolean; begin if other = nil then raise new System.ArgumentNullException('other', 'Null object is not iterable'); var c1 := wrappee.Count; var c2 := other.Count(); if (c1 = 0) or (c2 = 0) then Result := true else begin if c1 >= c2 then Result := other.All(elem -> not wrappee.Contains(elem)) else begin var otherSet := new HashSet(other); Result := wrappee.All(elem -> not otherSet.Contains(elem)); end; end; end; function get_keys(dct: Dictionary):= dct.keys; function get_values(dct: Dictionary):= dct.values; // TUPLES BEGIN function CreateTuple( v1: T1; v2: T2 ): System.Tuple := (v1, v2); function CreateTuple( v1: T1; v2: T2; v3: T3 ): System.Tuple := (v1, v2, v3); function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4 ): System.Tuple := (v1, v2, v3, v4); function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5 ): System.Tuple := (v1, v2, v3, v4, v5); function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6 ): System.Tuple := (v1, v2, v3, v4, v5, v6); function CreateTuple( v1: T1; v2: T2; v3: T3; v4: T4; v5: T5; v6: T6; v7: T7 ): System.Tuple := (v1, v2, v3, v4, v5, v6, v7); // TUPLES END //function &set(sq: sequence of T): &set; //begin // Result := new &set(sq); //end; function all(s: sequence of boolean): boolean; begin Result := true; foreach var elem in s do if (not elem) then begin Result := false; break; end; end; function any(s: sequence of boolean): boolean; begin Result := false; foreach var elem in s do if (elem) then begin Result := true; break; end; end; ///- function ToDictionary(Self: sequence of System.Tuple): dict; extensionmethod; begin Result := Self.ToDictionary(x->x[0],x->x[1]); end; function !empty_list(): empty_list := new empty_list(); function !empty_dict(): empty_dict := new empty_dict(); function round(val: real): integer := PABCSystem.round(val); function split(s: string): sequence of string; begin var temp := ''; var i := 0; while i <= s.Length - 1 do begin if (i <= s.Length - 1) and (s.Substring(i, 1) = ' ') then begin yield temp; temp := ''; i += 1; end else begin temp += s[i]; i += 1; end; end; yield temp; end; function !format(i: integer; fmt: string): string; begin if ((fmt.ToLower() = 'x') or (fmt = 'b') or (fmt = 'd')) then begin var HexChars := '0123456789abcdef'; if (fmt = 'X') then HexChars := HexChars.ToUpper(); var value := Cardinal(i); var radix := 10; if (fmt.ToLower() = 'x') then radix := 16; if (fmt = 'b') then radix := 2; if value = 0 then begin Result := '0'; Exit; end; while value > 0 do begin var digit := value mod radix; Result := HexChars[digit + 1] + Result; value := value div radix; end; Exit; end; if (fmt[1] = '.') then begin Result := !format(i + 0.0, fmt); Exit; end; raise new System.ArgumentException('Неверный формат для целочисленного аргумента'); end; function !format(val: real; fmt: string): string; begin var digits: integer; if (fmt.Length >= 3) and (fmt[1] = '.') and (fmt.EndsWith('f')) then begin var numStr := fmt.Substring(1, fmt.Length - 2); if TryStrToInt(numStr, digits) then begin var intPart := Trunc(val); if (digits = 0) then begin Result := intPart.ToString; Exit; end; var frac := Abs(val - intPart); var fracPart := Round(frac * Power(10, digits)); var fracStr := fracPart.ToString; while fracStr.Length < digits do fracStr := '0' + fracStr; Result := intPart.ToString + '.' + fracStr; Exit; end; end; raise new System.ArgumentException('Неверный формат для вещественного аргумента'); end; function !format(obj: object; fmt: string): string; begin Result := ''; raise new System.ArgumentException('Формат не соответствует типу данных выражения в f-строке'); end; end.