JavaScript の例(3) (TypeScript)
コンストラクターを1個にしました。イテレーターを保持する変数はやはりクラスの中には書けません。これはどうすれば良いのかわかりません。Visual Studioでこれを実行すると出力が「出力」の領域に出ないので出力がよくわかりません。これは調査したいと思います。
class LongDecimal { decimals: Array<number>; constructor(numbers: Iterable<number>) { this.decimals = []; for (var n of numbers) { this.decimals.push(n); } } static Align0<T>(xs: T[], len: number, z: T): T[] { var result: T[] = []; for (var xd of xs) { result.push(xd); } for (var i = xs.length; i < len; i++) { result.push(z); } return result; } static ZipWith<T, U>(f: (x: T, y: T) => U, xs: T[], ys: T[]): U[] { var result: U[] = []; for (var i = 0; i < xs.length && i < ys.length; i++) { result.push(f(xs[i], ys[i])); } return result; } static ZipWith0<T, U>(z: T, f: (x: T, y: T) => U, xs: T[], ys: T[]): U[] { var xsx: T[] = LongDecimal.Align0(xs, ys.length, z); var ysx: T[] = LongDecimal.Align0(ys, xs.length, z); return LongDecimal.ZipWith(f, xsx, ysx); } static CarryStep(carry_and_dec: [number, LongDecimal], x: number): [number, LongDecimal] { var [carry, dec]: [number, LongDecimal] = carry_and_dec; var newdec = new LongDecimal([(x + carry) % 10].concat(dec.decimals)); return [Math.floor((x + carry) / 10), newdec]; } static Replicate<T>(times: number, val: T): T[] { var result: T[] = []; for (var i = 0; i < times; i++) { result.push(val); } return result; } static LookUpFirst<T, U>(f: (key: T) => boolean, pairs: [T, U][]): U { for (var [key, val] of pairs) { if (f(key)) { return val; } } // 見つからないときは何も返さない } Sum_1(n: number): LongDecimal { return new LongDecimal([this.decimals[0] + n].concat(this.decimals.slice(1))); } Decimalize(c: number, leave: boolean): LongDecimal { var [carry, dec]: [number, LongDecimal] = this.decimals.reduceRight(LongDecimal.CarryStep, [c, new LongDecimal([])]); if (leave && carry != 0) { return dec.Sum_1(carry * 10); } else { return dec; } } Shift(e: number): LongDecimal { return new LongDecimal(LongDecimal.Replicate(e, 0).concat(this.decimals)); } Product_1(xd: number): LongDecimal { return new LongDecimal(this.decimals.map(yd => xd * yd)); } CollectShiftMult(y: LongDecimal): LongDecimal[] { var result: LongDecimal[] = []; var e = 0; for (var xd of this.decimals) { result.push(y.Product_1(xd).Shift(e)); e++; } return result; } static EqualAndLess(x: number, y: number): [boolean, boolean] { return [x == y, x < y]; } Sum(y: LongDecimal): LongDecimal { var x: LongDecimal = this; return new LongDecimal(LongDecimal.ZipWith0(0, (a, b) => a + b, x.decimals, y.decimals)).Decimalize(0, true); } Difference(y: LongDecimal): LongDecimal { var x: LongDecimal = this; var yds: number[] = LongDecimal.Align0(y.decimals, x.decimals.length, 0); return new LongDecimal(LongDecimal.ZipWith0(0, (a, b) => a + b, x.decimals, yds.map(a => 9 - a))).Decimalize(1, false); } Product(y: LongDecimal): LongDecimal { var x: LongDecimal = this; return x.CollectShiftMult(y).reduce((a, b) => a.Sum(b), new LongDecimal([])); } Equal(y: LongDecimal): boolean { var x: LongDecimal = this; return LongDecimal.ZipWith0(0, (a, b) => a == b, x.decimals, y.decimals).every(b => b); } NotEqual(y: LongDecimal): boolean { var x: LongDecimal = this; return !(x.Equal(y)); } Less(y: LongDecimal): boolean { var x: LongDecimal = this; if (x.Equal(y)) { return false; } return LongDecimal.LookUpFirst(key => !key, LongDecimal.ZipWith0(0, LongDecimal.EqualAndLess, x.decimals, y.decimals)); } LessOrEqual(y: LongDecimal): boolean { var x: LongDecimal = this; return x.Less(y) || x.Equal(y); } Greater(y: LongDecimal): boolean { var x: LongDecimal = this; return !(x.LessOrEqual(y)); } GreaterOrEqual(y: LongDecimal): boolean { var x: LongDecimal = this; return !(x.Less(y)); } Print(): string { var res: string = ""; var count: number = 0; for (var d of this.decimals) { if (count == 1) { res += "."; } res += d; count++; } return res; } } class Numbers { number: LongDecimal; square_difference: LongDecimal; scale: number; current_digit: number; constructor(number: LongDecimal, square_difference: LongDecimal, scale: number) { this.number = number; this.square_difference = square_difference; this.scale = scale; this.current_digit = 0; } get CurrentDigit(): number { return this.current_digit; } GetNextDecimalDigit(): number { var two: LongDecimal = new LongDecimal([2]); for (var dd: number = 9; dd >= 0; dd--) { var zd: LongDecimal = new LongDecimal([dd]).Shift(this.scale); var number_sq_diff: LongDecimal = this.number.Product(zd).Product(two).Sum(zd.Product(zd)); if (number_sq_diff.LessOrEqual(this.square_difference)) { this.number = this.number.Sum(zd); this.square_difference = this.square_difference.Difference(number_sq_diff); this.scale++; this.current_digit = dd; return dd; } } return 0; } } class NumbersGenerator { GetNextDecimalDigit(): number { return generator_gen.next().value; } *GenerateDecimal(): Iterable<number> { var number: LongDecimal = new LongDecimal([]); var square_difference: LongDecimal = new LongDecimal([3]); var nums: Numbers = new Numbers(number, square_difference, 0); for (; ;) { yield nums.GetNextDecimalDigit(); } } } class NumbersServer { current_numbers: Numbers; GetNumbers(numbers: Numbers): Numbers { var current = generator_server_gen.next(numbers); return current.value; } SetNumbers(numbers): void { this.current_numbers = numbers; } *GenerateDecimalServer(): Iterable<Numbers> { var number: LongDecimal = new LongDecimal([]); var square_difference: LongDecimal = new LongDecimal([3]); var current_numbers: Numbers = new Numbers(number, square_difference, 0); for (; ;) { current_numbers = yield current_numbers; } } } var generator_gen; var generator_server_gen; function* Iterate<T>(next: (T) => T, init: T): Iterable<T> { for (; ;) { yield init; init = next(init); } } function* Take<T>(n: number, generator: Iterable<T>): Iterable<T> { var count = 0; for (var d of generator) { yield d; if (count == n) { break; } count++; } } function* Map_<T>(f: (T) => T, list: Iterable<T>): Iterable<T> { for (var d of list) { yield f(d); } } function NextNumbers(numbers): Numbers { numbers.GetNextDecimalDigit(); return numbers; } function Repeat(count: number, f: () => string): string { var res: string = ""; for (var i = 0; i < count; i++) { res = f(); } return res; } class Calc { count: number; generator: NumbersGenerator; generator_server: NumbersServer; result_number: LongDecimal; constructor() { this.count = 21; this.generator = new NumbersGenerator(); this.generator_server = new NumbersServer(); this.result_number = new LongDecimal([]); generator_gen = this.generator.GenerateDecimal(); generator_server_gen = this.generator_server.GenerateDecimalServer(); } RepeatGenerator(): string { for (var e = 0; e < this.count; e++) { this.result_number = this.result_number.Sum(new LongDecimal([this.generator.GetNextDecimalDigit()]).Shift(e)); } return this.result_number.Print(); } RepeatServer(): string { for (var e = 0; e < this.count; e++) { var current_numbers = this.generator_server.GetNumbers(current_numbers); var dd = current_numbers.GetNextDecimalDigit(); this.generator_server.SetNumbers(current_numbers); this.result_number = this.result_number.Sum(new LongDecimal([dd]).Shift(e)); } return this.result_number.Print(); } IterateGenerator(): string { return new LongDecimal(Take(this.count, this.generator.GenerateDecimal())).Print(); } IterateServer(): string { var number = new LongDecimal([]); var square_difference = new LongDecimal([3]); var init_numbers = new Numbers(number, square_difference, 0); init_numbers.GetNextDecimalDigit(); return new LongDecimal(Map_(numbers => numbers.CurrentDigit, Take(this.count, Iterate(NextNumbers, init_numbers)))).Print(); } } console.log(new Calc().RepeatGenerator()); console.log(new Calc().RepeatServer()); console.log(new Calc().IterateGenerator()); console.log(new Calc().IterateServer());