「双方向リスト (doubly-linked list)」と、それを使って実装した「両端キュー (deque)」のプログラムです。双方向リストの説明は拙作のページをお読みください。
//
// deque.js : 双方向リストとディーキュー
//
// Copyright (c) 2025 Makoto Hiroi
//
// Released under the MIT license
// https://opensource.org/license/mit/
//
// セル
class Cell {
constructor(x, n, p) {
this._item = x;
this._next = n;
this._prev = p;
}
get item() { return this._item; }
set item(x) { this._item = x; }
get next() { return this._next; }
set next(x) { this._next = x; }
get prev() { return this._prev; }
set prev(x) { this._prev = x; }
// n 個のセルをたどる
nth(n, end = false) {
let cp = this;
while (n-- > 0) cp = end ? cp.prev : cp.next;
return cp;
}
}
// 空リストの生成
function make_empty() {
let cp = new Cell(null, null, null);
cp.next = cp;
cp.prev = cp;
return cp;
}
// 双方向リスト
class DList {
constructor() {
this._top = make_empty();
this._len = 0;
}
get top() { return this._top; }
get length() { return this._len; }
set length(x) { this._len = x; }
isEmpty() { return this._len == 0; }
clear() {
let header = this.top;
header.prev = header;
header.next = header;
this._len = 0;
}
// 参照
nth(n, end = false) {
if (n < this.length) {
return this.top.nth(n + 1, end).item;
}
return;
}
// 書き換え
set(n, x, end = false) {
if (n < this.length) {
this.top.nth(n + 1, end).item = x;
return x;
}
return;
}
// 挿入
add(n, x, end = false) {
if (n <= this.length) {
let p = this.top.nth(n, end);
let q = end ? p.prev : p.next;
if (end) {
// q - c - p
let c = new Cell(x, p, q);
q.next = c;
p.prev = c;
} else {
// p - c - q
let c = new Cell(x, q, p);
p.next = c;
q.prev = c;
}
this.length++;
return x;
}
return;
}
// 削除
delete(n, end = false) {
if (n < this.length) {
let c = this.top.nth(n + 1, end);
let x = c.item;
let p = c.next;
let q = c.prev;
// q - c - p
q.next = p;
p.prev = q;
this.length--;
return x;
}
return;
}
// ジェネレータ
*makeGen(end = false) {
let cp = this.top;
let n = this.length;
while (n-- > 0) {
cp = end ? cp.prev : cp.next;
yield cp.item;
}
}
*[Symbol.iterator]() { yield* this.makeGen(); }
//
// 探索
//
find(pred, end = false) {
for (let x of this.makeGen(end)) {
if (pred(x)) return x;
}
return false;
}
findIndex(pred, end = false) {
let i = 0;
for (let x of this.makeGen(end)) {
if (pred(x)) return i;
i++;
}
return -1;
}
indexOf(x, end = false) {
return this.findIndex(y => x == y, end);
}
//
// 高階関数
//
map(fn) {
let d = new DList();
for (let x of this) d.add(0, fn(x), true);
return d;
}
filter(pred) {
let d = new DList();
for (let x of this) {
if (pred(x)) d.add(0, x, true);
}
return d;
}
reduce(fn, a, end = false) {
for (let x of this.makeGen(end)) {
a = fn(a, x);
}
return a;
}
forEach(fn, end = false) {
for (let x of this.makeGen(end)) fn(x);
}
// 文字列
toString() {
return "(" + [...this].join(",") + ")";
}
// スタティックメソッド
static from(iter) {
let d = new DList();
for (let x of iter) d.add(0, x, true);
return d;
}
static of(...args) { return DList.from(args); }
}
// 両端キュー
class Deque {
constructor() {
this._que = new DList();
}
get que() { return this._que; }
isEmpty() { return this.que.isEmpty(); }
length() { return this.que.length; }
clear() { this.que.clear(); }
push_front(x) { return this.que.add(0, x); }
pop_front() { return this.que.delete(0); }
peek_front() { return this.que.nth(0); }
push_back(x) { return this.que.add(0, x, true); }
pop_back() { return this.que.delete(0, true); }
peek_back() { return this.que.nth(0, true); }
toString() { return this.que.toString(); }
}
export { DList, Deque };
//
// test_deque.js : 双方向リストとディーキューのテスト
//
// Copyright (c) 2025 Makoto Hiroi
//
// Released under the MIT license
// https://opensource.org/license/mit/
//
import { DList, Deque } from './deque.js';
var a = new DList();
console.log('%s', a); // ()
console.log(a.isEmpty()); // true
console.log(a.length); // 0
for (let i = 1; i <= 4; i++) {
a.add(0, i);
}
console.log('%s', a); // (4,3,2,1)
console.log(a.isEmpty()); // false
console.log(a.length); // 4
for (let i = 5; i <= 8; i++) {
a.add(0, i, true);
}
console.log('%s', a); // (4,3,2,1,5,6,7,8)
console.log(a.isEmpty()); // false
console.log(a.length); // 8
for (let i = 0; i < a.length; i++) console.log(a.nth(i))
for (let i = 0; i < a.length; i++) console.log(a.nth(i, true))
for (let i = 0; i < a.length; i++) a.set(i, a.nth(i) + i);
console.log('%s', a); // 4,4,4,4,9,11,13,15
for (let i = 0; i < a.length; i++) a.set(i, a.nth(i, true) + i, true);
console.log('%s', a); // 11,10,9,8,12,13,14,15
console.log(a.delete(0)); // 11
console.log(a.delete(3)); // 12
console.log(a.delete(0, true)); // 15
console.log(a.delete(3, true)); // 9
console.log(a.length) // 4
console.log('%s', a); // 10, 8, 13, 14
a.clear();
console.log(a.isEmpty()); // true
console.log(a.length); // 0
for (let i = 1; i <= 8; i++) a.add(0, i, true);
for (let x of a) console.log(x); // 1,2,3,4,5,6,7,8
for (let x of a.makeGen(true)) console.log(x); // 8,7,6,5,4,3,2,1
console.log(a.find(x => x % 2 == 0)); // 2
console.log(a.find(x => x % 2 == 0, true)); // 8
console.log(a.find(x => x > 8)); // false
console.log(a.findIndex(x => x % 2 == 0)); // 1
console.log(a.findIndex(x => x % 2 == 0, true)); // 0
console.log(a.findIndex(x => x > 8)); // -1
console.log(a.indexOf(2)); // 1
console.log(a.indexOf(8, true)); // 0
console.log(a.indexOf(9)); // -1
console.log('%s', a.map(x => x * x)); // 1 4 9 ...
console.log('%s', a.filter(x => x % 2 == 0)); // 2,4,6,8
console.log(a.reduce((a, x) => a + x, 0)); // 36
console.log(a.reduce((a, x) => a + x, 0, true)); // 36
a.forEach(console.log);
a.forEach(console.log, true);
console.log('%s', DList.from([1,2,3,4,5,6,7,8]));
console.log('%s', DList.of(1,2,3,4,5,6,7,8));
// 両端キュー
console.log("----- Deque -----");
var b = new Deque();
console.log('%s', b); // ()
console.log(b.isEmpty()); // true
console.log(b.length()); // 0
for (let i = 1; i <= 4; i++) b.push_front(i);
console.log('%s', b); // (4,3,2,1)
console.log(b.isEmpty()); // false
console.log(b.length()); // 4
for (let i = 1; i <= 4; i++) console.log(b.pop_front()); // 4 3 2 1
console.log('%s', b); // ()
console.log(b.isEmpty()); // true
console.log(b.length()); // 0
for (let i = 1; i <= 4; i++) b.push_back(i);
console.log('%s', b); // (1,2,3,4)
console.log(b.isEmpty()); // false
console.log(b.length()); // 4
for (let i = 1; i <= 4; i++) console.log(b.pop_back()); // 4 3 2 1
console.log('%s', b); // ()
console.log(b.isEmpty()); // true
console.log(b.length()); // 0
for (let i = 1; i <= 8; i++) b.push_back(i);
console.log('%s', b); // (1,2,3,4,5,6,7,8
console.log(b.isEmpty()); // false
console.log(b.length()); // 8
console.log(b.peek_front()); // 1
console.log(b.peek_back()); // 8
while (!b.isEmpty()) console.log(b.pop_front()); // 1 2 3 4 ...
$ node test_deque.js () true 0 (4,3,2,1) false 4 (4,3,2,1,5,6,7,8) false 8 4 3 2 1 5 6 7 8 8 7 6 5 1 2 3 4 (4,4,4,4,9,11,13,15) (11,10,9,8,12,13,14,15) 11 12 15 9 4 (10,8,13,14) true 0 1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1 2 8 false 1 0 -1 1 0 -1 (1,4,9,16,25,36,49,64) (2,4,6,8) 36 36 1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1 (1,2,3,4,5,6,7,8) (1,2,3,4,5,6,7,8) ----- Deque ----- () true 0 (4,3,2,1) false 4 4 3 2 1 () true 0 (1,2,3,4) false 4 4 3 2 1 () true 0 (1,2,3,4,5,6,7,8) false 8 1 8 1 2 3 4 5 6 7 8
B───D───F
/│ │
A │ │
\│ │
C───E───G
図 : 経路図
//
// keiro_deque.js : 経路の探索 (deque のサンプル)
//
// Copyright (c) 2025 Makoto Hiroi
//
// Released under the MIT license
// https://opensource.org/license/mit/
//
import { DList, Deque } from './deque.js';
// 1 ----- 3 ----- 5
// / | |
// 0 | |
// \ | |
// 2 ----- 4 ----- 6
// 隣接リスト
const adjacent = [
[1, 2], // 0
[0, 2, 3], // 1
[0, 1, 4], // 2
[1, 4, 5], // 3
[2, 3, 6], // 4
[3], // 5
[4] // 6
];
// 深さ優先探索
function dfs(goal, path) {
let p = path.nth(0, true);
if (p == goal) {
console.log('%s', path);
} else {
for (let q of adjacent[p]) {
if (path.indexOf(q) == -1) {
path.add(0, q, true);
dfs(goal, path);
path.delete(0, true);
}
}
}
}
// 実行
console.log('----- depth first search -----');
dfs(6, DList.of(0));
// 幅優先探索
function bfs(start, goal) {
let q = new Deque();
q.push_back(DList.of(start));
while (!q.isEmpty()) {
let xs = q.pop_front();
let x = xs.nth(0, true);
if (x == goal) {
console.log('%s', xs);
} else {
for (let y of adjacent[x]) {
if (xs.indexOf(y) == -1) {
let ys = DList.from([...xs]);
ys.add(0, y, true);
q.push_back(ys);
}
}
}
}
}
console.log('----- breadth first search -----');
bfs(0, 6);
// 反復深化
function dfsi(path, goal, limit) {
if (path.length == limit) {
if (path.nth(0, true) == goal) {
console.log('%s', path);
}
} else {
for (let p of adjacent[path.nth(0, true)]) {
if (path.indexOf(p) == -1) {
path.add(0, p, true);
dfsi(path, goal, limit);
path.delete(0, true);
}
}
}
}
function ids(start, goal) {
for (let limit = 1; limit <= adjacent.length; limit++) {
console.log(`----- ${limit} -----`);
dfsi(DList.of(start), goal, limit);
}
}
console.log('----- ids -----');
ids(0, 6);
$ node keiro_dlist.js ----- depth first search ----- (0,1,2,4,6) (0,1,3,4,6) (0,2,1,3,4,6) (0,2,4,6) ----- breadth first search ----- (0,2,4,6) (0,1,2,4,6) (0,1,3,4,6) (0,2,1,3,4,6) ----- ids ----- ----- 1 ----- ----- 2 ----- ----- 3 ----- ----- 4 ----- (0,2,4,6) ----- 5 ----- (0,1,2,4,6) (0,1,3,4,6) ----- 6 ----- (0,2,1,3,4,6) ----- 7 -----
整列 (sorting) は、ある規則に従ってデータを順番に並べ換える操作です。たとえば、データが整数であれば大きい順に並べる、もしくは小さい順に並べます。一般に、このような操作を「ソート」と呼んでいます。ソートは昔から研究されている分野で、優秀なアルゴリズムが確立しています。
ソートは大きく分けると、内部ソート (internal sort) と外部ソート (external sort) にわかれます。内部ソートはすべてのデータをメモリに読み込んでソートします。外部ソートはメモリにすべて読み込むことができない巨大なデータをソートするときに使われ、外部記憶装置に途中経過を記憶させながらソートします。
JavaScript の配列 (と型付き配列) にはソートを行うメソッド sort() がありますが、私達でもプログラムすることができます。ここでは代表的なソートアルゴリズムをいくつか実装してみましょう。アルゴリズムの詳しい説明は拙作のページをお読みください。
//
// sort.js : ソート
//
// Copyright (c) 2025 Makoto Hiroi
//
// Released under the MIT license
// https://opensource.org/license/mit/
//
function make_data(x) {
// x は生成するデータの個数
// 乱数
let a = new Float64Array(x);
for (let i = 0; i < x; i++) a[i] = Math.random();
// 昇順
let b = new Float64Array(x);
for (let i = 0; i < x; i++) b[i] = i + 1.0;
// 降順
let c = new Float64Array(x);
for (let i = 0; i < x; i++) c[i] = x - i;
// 山型
let d = new Float64Array(x);
let m = Math.floor(x / 2);
for (let i = 0; i < m; i++) d[i] = i + 1.0;
for (let i = m; i < x; i++) d[i] = x - i;
return [a, b, c, d];
}
function check(xs) {
for (let i = 0; i < xs.length - 1; i++) {
if (xs[i] > xs[i + 1]) throw new Error("sort error");
}
}
function test(func, xs) {
for (let x of xs) {
let rs = [];
for (let ys of make_data(x)) {
let s = new Date().getTime();
func(ys);
let e = new Date().getTime();
rs.push(e - s);
check(ys);
}
console.log(x, ":", rs);
}
}
// メソッド sort() の時間計測
function test1(xs) {
for (let x of xs) {
let rs = [];
for (let ys of make_data(x)) {
let s = new Date().getTime();
ys.sort();
let e = new Date().getTime();
rs.push(e - s);
check(ys);
}
console.log(x, ":", rs);
}
}
// バブルソート
function buble_sort(buff) {
let k = buff.length - 1;
for (let i = 0; i < k; i++) {
for (let j = k; j > i; j--) {
if (buff[j - 1] > buff[j]) {
let temp = buff[j];
buff[j] = buff[j - 1];
buff[j - 1] = temp;
}
}
}
return buff;
}
// 単純挿入ソート
function insert_sort(buff) {
let k = buff.length;
for (let i = 1; i < k; i++) {
let temp = buff[i];
let j = i - 1;
for (; j >=0 && temp < buff[j]; j--) {
buff[j + 1] = buff[j];
}
buff[j + 1] = temp;
}
return buff;
}
// シェルソート
function shell_sort(buff) {
let k = buff.length;
let gap = 1;
while (gap < Math.floor(k / 9)) gap = gap * 3 + 1;
while (gap > 0) {
for (let i = gap; i < k; i++) {
let temp = buff[i];
let j = i - gap;
while (j >= 0 && temp < buff[j]) {
buff[j + gap] = buff[j];
j -= gap;
}
buff[j + gap] = temp;
}
gap = Math.floor(gap / 3);
}
return buff;
}
// クイックソート (単純版)
function qsort(buff, low, high) {
let pivot = buff[low + Math.floor((high - low)/2)];
let i = low;
let j = high;
while (true) {
while (pivot > buff[i]) i++;
while (pivot < buff[j]) j--;
if (i >= j) break;
let temp = buff[i];
buff[i] = buff[j];
buff[j] = temp;
i++;
j--;
}
if (low < i - 1) qsort(buff, low, i - 1);
if (high > j + 1) qsort(buff, j + 1, high);
}
function quick_sort(buff) {
qsort(buff, 0, buff.length - 1);
return buff;
}
// 改良版
// 枢軸の選択 (median-of-3)
function select_pivot(buff, low, high) {
let a = buff[low];
let b = buff[low + Math.floor((high - low) / 2)];
let c = buff[high];
if (a > b) [a, b] = [b, a];
if (b > c) {
b = c;
if (a > b) b = a;
}
return b;
}
const limit = 10;
function qsort2(buff, low, high) {
let stack = [];
while (true) {
if ((high - low) <= limit) {
if (stack.length == 0) break;
[low, high] = stack.pop();
} else {
let pivot = select_pivot(buff, low, high)
let i = low
let j = high
while (true) {
while (pivot > buff[i]) i++;
while (pivot < buff[j]) j--;
if (i >= j) break;
let temp = buff[i];
buff[i] = buff[j];
buff[j] = temp;
i++;
j--;
}
if (i - low > high - j) {
stack.push([low, i - 1]);
low = j + 1;
} else {
stack.push([j + 1, high]);
high = i - 1;
}
}
}
insert_sort(buff)
}
function quick_sort2(buff) {
qsort2(buff, 0, buff.length - 1);
return buff;
}
> test(buble_sort, [10000,20000,40000,80000]) 10000 : [ 215, 83, 115, 100 ] 20000 : [ 888, 332, 466, 402 ] 40000 : [ 3790, 1315, 1850, 1599 ] 80000 : [ 15422, 5283, 7385, 6336 ] undefined > test(insert_sort, [10000,20000,40000,80000]) 10000 : [ 45, 0, 83, 41 ] 20000 : [ 174, 0, 328, 164 ] 40000 : [ 667, 1, 1318, 662 ] 80000 : [ 2641, 0, 5302, 2643 ] undefined
> test(shell_sort, [10000,20000,40000,80000]) 10000 : [ 7, 1, 0, 1 ] 20000 : [ 4, 0, 1, 1 ] 40000 : [ 8, 3, 2, 3 ] 80000 : [ 18, 5, 6, 5 ] undefined > test(shell_sort, [100000,200000,400000,800000]) 100000 : [ 22, 5, 7, 7 ] 200000 : [ 49, 12, 14, 13 ] 400000 : [ 108, 25, 31, 30 ] 800000 : [ 243, 54, 66, 64 ] undefined
> test(quick_sort, [10000,20000,40000,80000])
10000 : [ 2, 0, 0, 77 ]
Uncaught RangeError: Maximum call stack size exceeded
at qsort (REPL4:99:15)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
at qsort (REPL4:113:22)
> test(quick_sort2, [10000,20000,40000,80000]) 10000 : [ 10, 1, 1, 1 ] 20000 : [ 5, 2, 1, 3 ] 40000 : [ 5, 1, 1, 5 ] 80000 : [ 12, 3, 4, 11 ] undefined > test(quick_sort2, [100000,200000,400000,800000]) 100000 : [ 14, 4, 4, 15 ] 200000 : [ 30, 7, 9, 31 ] 400000 : [ 63, 15, 16, 68 ] 800000 : [ 181, 33, 34, 152 ] undefined
> test1([100000, 200000, 400000, 800000]) 100000 : [ 13, 5, 5, 17 ] 200000 : [ 24, 12, 9, 35 ] 400000 : [ 53, 27, 19, 75 ] 800000 : [ 110, 54, 40, 159 ] undefined
> var a = [1, 10, 2, 20, 3, 30] undefined > a.sort() [ 1, 10, 2, 20, 3, 30 ] > a.sort((a, b) => a - b) [ 1, 2, 3, 10, 20, 30 ]
> var b = new Int32Array([1,10,2,20,3,30]) undefined > b Int32Array(6) [ 1, 10, 2, 20, 3, 30 ] > b.sort() Int32Array(6) [ 1, 2, 3, 10, 20, 30 ] > b Int32Array(6) [ 1, 2, 3, 10, 20, 30 ] > b.sort((a, b) => b - a) Int32Array(6) [ 30, 20, 10, 3, 2, 1 ]
約数 (divisor) は整数 n を割り切る整数のことです。たとえば、24 の正の約数は 1, 2, 3, 4, 6, 8, 12, 24 の 8 個あります。ここでは正の約数を考えることにします。
正の約数が 1 と自分自身しかない自然数のことを素数といいます。1 ではない正整数で、素数ではないものを合成数といいます。合成数は素数の積の形に書き表すことができます。これを「素因数分解 (prime factorization)」といいます。
たとえば、6 = 2 * 3, 12 = 22 * 3, 30 = 2 * 3 * 5 と素因数分解することができます。素数の並べ方を除けば、素因数分解はただの一通りしかありません。これを「素因数分解の一意性」といいます。
詳しい説明は拙作のページをお読みください。
//
// divisor.js : 約数
//
// Copyright (c) 2025 Makoto Hiroi
//
// Released under the MIT license
// https://opensource.org/license/mit/
//
// 素因数分解
function factor_sub(n, p){
let c = 0n;
while (n % p == 0n) {
n /= p;
c++;
}
return [c, n]
}
function factorization(n) {
let ps = [];
let wheel = [1n, 2n, 2n, 4n, 2n, 4n, 2n, 4n, 6n, 2n, 6n];
let [i, s] = [0, 3n];
let [x, c, m] = [2n, 0n, n];
while (m >= x * x) {
[c, m] = factor_sub(m, x);
if (c > 0n) ps.push([x, c])
x += wheel[i]
if (++i >= wheel.length) i = s;
}
if (m > 1n) ps.push([m, 1n]);
return ps;
}
// 約数の個数
function divisor_count(n) {
return factorization(n).reduce((a, [p, q]) => a * (q + 1n), 1n);
}
// 約数の合計値
function divisor_total(n) {
return factorization(n).reduce((a, [p, q]) => a * (p ** (q + 1n) - 1n) / (p - 1n), 1n);
}
// p ** q の約数を求める
function divisor_sub(p, q) {
let a = [];
for (let i = 0n; i <= q; i++) a.push(p ** i);
return a;
}
// 直積集合
function product(xs, ys) {
let a = [];
for (let x of xs) {
for (let y of ys) a.push(x * y);
}
return a;
}
// 比較
function compare(a, b) {
if (a > b) return 1;
if (a == b) return 0
return -1;
}
// 約数を求める
function divisors(n) {
let xs = factorization(n);
return xs.reduce((a, [p, q]) => product(a, divisor_sub(p, q)), [1n]).sort(compare);
}
// 完全数
function perfect_number(n) {
for (let x = 2n; x <= n; x++) {
if (divisor_total(x) - x == x) {
console.log('%s', x);
}
}
}
// 友愛数
function amicable_number(n) {
for (let x = 2n; x <= n; x++) {
let m = divisor_total(x) - x;
if (m < x && x == divisor_total(m) - m) {
console.log('%s %s', m, x);
}
}
}
// 約数関数
function divisor_sigma(n, k) {
if (k == 0) return divisor_count(n);
let xs = factorization(n);
return xs.reduce((a, [p, q]) => a * (p ** (k * (q + 1n)) - 1n) / (p ** k - 1n), 1n);
}
// オイラーのトーシェント関数 (公式)
function totient(n) {
let xs = factorization(n);
return xs.reduce((d, [p, q]) => d * (p - 1n) / p, n);
}
> var a = [24n, 12345678n, 123456789n, 1234567890n, 1111111111n]
undefined
> for (let x of a) console.log(x, factorization(x));
24n [ [ 2n, 3n ], [ 3n, 1n ] ]
12345678n [ [ 2n, 1n ], [ 3n, 2n ], [ 47n, 1n ], [ 14593n, 1n ] ]
123456789n [ [ 3n, 2n ], [ 3607n, 1n ], [ 3803n, 1n ] ]
1234567890n [ [ 2n, 1n ], [ 3n, 2n ], [ 5n, 1n ], [ 3607n, 1n ], [ 3803n, 1n ] ]
1111111111n [ [ 11n, 1n ], [ 41n, 1n ], [ 271n, 1n ], [ 9091n, 1n ] ]
undefined
> for (let x of a) console.log(x, divisor_count(x));
24n 8n
12345678n 24n
123456789n 12n
1234567890n 48n
1111111111n 16n
undefined
> for (let x of a) console.log(x, divisor_total(x));
24n 60n
12345678n 27319968n
123456789n 178422816n
1234567890n 3211610688n
1111111111n 1246404096n
undefined
> for (let x of a) console.log(x, divisors(x))
24n [
1n, 2n, 3n, 4n,
6n, 8n, 12n, 24n
]
12345678n [
1n, 2n, 3n,
6n, 9n, 18n,
47n, 94n, 141n,
282n, 423n, 846n,
14593n, 29186n, 43779n,
87558n, 131337n, 262674n,
685871n, 1371742n, 2057613n,
4115226n, 6172839n, 12345678n
]
123456789n [
1n, 3n,
9n, 3607n,
3803n, 10821n,
11409n, 32463n,
34227n, 13717421n,
41152263n, 123456789n
]
1234567890n [
1n, 2n, 3n, 5n,
6n, 9n, 10n, 15n,
18n, 30n, 45n, 90n,
3607n, 3803n, 7214n, 7606n,
10821n, 11409n, 18035n, 19015n,
21642n, 22818n, 32463n, 34227n,
36070n, 38030n, 54105n, 57045n,
64926n, 68454n, 108210n, 114090n,
162315n, 171135n, 324630n, 342270n,
13717421n, 27434842n, 41152263n, 68587105n,
82304526n, 123456789n, 137174210n, 205761315n,
246913578n, 411522630n, 617283945n, 1234567890n
]
1111111111n [
1n, 11n,
41n, 271n,
451n, 2981n,
9091n, 11111n,
100001n, 122221n,
372731n, 2463661n,
4100041n, 27100271n,
101010101n, 1111111111n
]
undefined
> perfect_number(10000n)
6n
28n
496n
8128n
undefined
> amicable_number(100000n)
220n 284n
1184n 1210n
2620n 2924n
5020n 5564n
6232n 6368n
10744n 10856n
12285n 14595n
17296n 18416n
66928n 66992n
67095n 71145n
63020n 76084n
69615n 87633n
79750n 88730n
undefined
> for (let x of a) console.log(x, divisor_sigma(x, 0n))
24n 8n
12345678n 24n
123456789n 12n
1234567890n 48n
1111111111n 16n
undefined
> for (let x of a) console.log(x, divisor_sigma(x, 1n))
24n 60n
12345678n 27319968n
123456789n 178422816n
1234567890n 3211610688n
1111111111n 1246404096n
undefined
> for (let x of a) console.log(x, divisor_sigma(x, 2n))
24n 850n
12345678n 214137553857500n
123456789n 17123257639169500n
1234567890n 2226023493092035000n
1111111111n 1245528410223519376n
undefined
> for (let x of a) console.log(x, totient(x))
24n 8n
12345678n 4027392n
123456789n 82260072n
1234567890n 329040288n
1111111111n 981720000n