>>> from collections import deque >>> for x in range(4): d.append(x) ... >>> d deque([0, 1, 2, 3]) >>> for _ in range(4): print(d.popleft()) ... 0 1 2 3 >>> d deque([]) >>> d.extend(range(1, 10)) >>> d deque([1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> len(d) 9 >>> d.reverse() >>> d deque([9, 8, 7, 6, 5, 4, 3, 2, 1]) >>> d.rotate(3) >>> d deque([3, 2, 1, 9, 8, 7, 6, 5, 4])
#
# deque.py : リングバッファによるディーキューの実装
#
# Copyright (C) 2018 Makoto Hiroi
#
class Deque:
def __init__(self, size):
self.buff = [None] * size
self.front = 0
self.rear = 0
self.cnt = 0
# 先頭からデータを取り出す
def pop_front(self):
if self.cnt == 0:
raise IndexError("Deque is empty")
x = self.buff[self.front]
self.front += 1
self.cnt -= 1
if self.front == len(self.buff):
self.front = 0
return x
# 末尾からデータを取り出す
def pop_back(self):
if self.cnt == 0:
raise IndexError("Deque is empty")
self.rear -= 1
self.cnt -= 1
if self.rear < 0:
self.rear = len(self.buff) - 1
return self.buff[self.rear]
# 末尾にデータを追加
def push_back(self, x):
if self.cnt == len(self.buff):
# 先頭からデータを取り出して捨てる
self.pop_front()
self.buff[self.rear] = x
self.rear += 1
self.cnt += 1
if self.rear == len(self.buff):
self.rear = 0
# 先頭にデータを追加する
def push_front(self, x):
if self.cnt == len(self.buff):
# 末尾からデータを取り出して捨てる
self.pop_back()
self.front -= 1
self.cnt += 1
if self.front < 0:
self.front = len(self.buff) - 1
self.buff[self.front] = x
# ジェネレータ
def each(self):
i = self.front
c = self.cnt
while c > 0:
yield self.buff[i]
i += 1
c -= 1
if i == len(self.buff): i = 0
# 空か?
def is_empty(self): return self.cnt == 0
# 空にする
def clear(self):
self.front = 0
self.rear = 0
self.cnt = 0
# 要素数を返す
def __len__(self): return self.cnt
# 表示
def __repr__(self):
s = 'Deque('
if self.cnt > 0:
for x in self.each():
s += '{}, '.format(x)
s = s[:-2]
s += ')'
return s
if __name__ == '__main__':
# 簡単なテスト
d = Deque(8)
print(d)
print(d.is_empty())
print(len(d))
for x in range(4): d.push_back(x)
print(d)
print(d.is_empty())
print(len(d))
for x in range(4, 8): d.push_front(x)
print(d)
print(d.is_empty())
print(len(d))
for _ in range(4): print(d.pop_front())
print(d)
print(d.is_empty())
print(len(d))
for _ in range(4): print(d.pop_back())
print(d)
print(d.is_empty())
print(len(d))
for x in range(10):
d.push_back(x)
print(d)
for x in range(10, 12):
d.push_front(x)
print(d)
Deque() True 0 Deque(0, 1, 2, 3) False 4 Deque(7, 6, 5, 4, 0, 1, 2, 3) False 8 7 6 5 4 Deque(0, 1, 2, 3) False 4 3 2 1 0 Deque() True 0 Deque(0) Deque(0, 1) Deque(0, 1, 2) Deque(0, 1, 2, 3) Deque(0, 1, 2, 3, 4) Deque(0, 1, 2, 3, 4, 5) Deque(0, 1, 2, 3, 4, 5, 6) Deque(0, 1, 2, 3, 4, 5, 6, 7) Deque(1, 2, 3, 4, 5, 6, 7, 8) Deque(2, 3, 4, 5, 6, 7, 8, 9) Deque(10, 2, 3, 4, 5, 6, 7, 8) Deque(11, 10, 2, 3, 4, 5, 6, 7)
>>> from heapq import * >>> a = [] >>> for x in [5,6,4,7,3,8,2,9,1]: heappush(a, x) ... >>> a [1, 2, 3, 4, 6, 8, 5, 9, 7] >>> for _ in range(9): print(heappop(a)) ... 1 2 3 4 5 6 7 8 9 >>> a [] >>> a = [9,8,7,6,5,4,3,2,1] >>> heapify(a) >>> a [1, 2, 3, 6, 5, 4, 7, 8, 9] >>> for _ in range(9): print(heappop(a)) ... 1 2 3 4 5 6 7 8 9
>>> a = b'12345678'
>>> a
b'12345678'
>>> a[0]
49
>>> a[7]
56
>>> a[2:6]
b'3456'
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> bytes(range(10))
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
>>> bytearray(10)
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> b = bytearray(a)
>>> b
bytearray(b'12345678')
>>> b[0] = ord('a')
>>> b
bytearray(b'a2345678')
num.to_bytes(length, byteorder) int.from_bytes(bytes, byteorder)
>>> a = 'あいうえお' >>> b = a.encode() >>> b b'\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a' >>> b.decode() 'あいうえお' >>> a = 97 >>> a.to_bytes(1, 'big') b'a' >>> int.from_bytes(b'a', 'big') 97
>>> import array
>>> a = array.array('l', range(8))
>>> a
array('l', [0, 1, 2, 3, 4, 5, 6, 7])
>>> a[0]
0
>>> a[7]
7
>>> a[5] *= 100
>>> a
array('l', [0, 1, 2, 3, 4, 500, 6, 7])
>>> a.append(1000)
>>> a
array('l', [0, 1, 2, 3, 4, 500, 6, 7, 1000])
>>> a.pop()
1000
>>> a
array('l', [0, 1, 2, 3, 4, 500, 6, 7])
>>> a = array.array('l', [1, 2, 3, 4])
>>> a
array('l', [1, 2, 3, 4])
>>> a.tolist()
[1, 2, 3, 4]
>>> b = a.tobytes()
>>> b
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00'
>>> c = array.array('l')
>>> c.frombytes(b)
>>> c
array('l', [1, 2, 3, 4])
>>> with open('test.dat', 'wb') as f:
... a.tofile(f)
...
>>> d = array.array('l')
>>> d
array('l')
>>> with open('test.dat', 'rb') as f:
... d.fromfile(f, 4)
...
>>> d
array('l', [1, 2, 3, 4])
xs.sort(key = None, reverse = False) => None sorted(iterable, key = None, reverse = False) => sorted_list
>>> a = [5, 6, 4, 7, 3, 8, 2, 9, 1, 0]
>>> a.sort()
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.sort(reverse=True)
>>> a
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> sorted(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> b = [('foo', 1), ('bar', 2), ('baz', 3), ('oops', 4)]
>>> b.sort(key = lambda x: x[0])
>>> b
[('bar', 2), ('baz', 3), ('foo', 1), ('oops', 4)]
>>> b.sort(key = lambda x: x[1])
>>> b
[('foo', 1), ('bar', 2), ('baz', 3), ('oops', 4)]
>>> sorted(b, key = lambda x: x[0])
[('bar', 2), ('baz', 3), ('foo', 1), ('oops', 4)]
>>> b
[('foo', 1), ('bar', 2), ('baz', 3), ('oops', 4)]
>>> from operator import itemgetter, attrgetter, methodcaller
>>> f1 = itemgetter(1)
>>> f1([1, 2, 3, 4, 5])
2
>>> a = [('foo', 1), ('bar', 2), ('baz', 3), ('oops', 4)]
>>> sorted(a, key = itemgetter(0))
[('bar', 2), ('baz', 3), ('foo', 1), ('oops', 4)]
>>> sorted(a, key = itemgetter(1))
[('foo', 1), ('bar', 2), ('baz', 3), ('oops', 4)]
>>> class Pair:
... def __init__(self, x, y):
... self.fst = x
... self.snd = y
... def get_fst(self): return self.fst
... def get_snd(self): return self.snd
... def __repr__(self): return 'Pair({},{})'.format(self.fst, self.snd)
...
>>> b = list(map(lambda xs: Pair(xs[0], xs[1]), a))
>>> b
[Pair(foo,1), Pair(bar,2), Pair(baz,3), Pair(oops,4)]
>>> sorted(b, key = attrgetter('fst'))
[Pair(bar,2), Pair(baz,3), Pair(foo,1), Pair(oops,4)]
>>> sorted(b, key = attrgetter('snd'))
[Pair(foo,1), Pair(bar,2), Pair(baz,3), Pair(oops,4)]
>>> sorted(b, key = methodcaller('get_fst'))
[Pair(bar,2), Pair(baz,3), Pair(foo,1), Pair(oops,4)]
>>> sorted(b, key = methodcaller('get_snd'))
[Pair(foo,1), Pair(bar,2), Pair(baz,3), Pair(oops,4)]
元のデータ 安定なソート 不安定なソート
(123, 'abc') (123, 'abc') (789, 'abc')
(456, 'def') (789, 'abc') (123, 'abc')
(789, 'abc') (456, 'def') (456, 'def')
図 : ソートの安定性
>>> a = [('foo', 1), ('bar', 3), ('bar', 2), ('bar', 1), ('baz', 4)]
>>> sorted(a, key = itemgetter(0))
[('bar', 3), ('bar', 2), ('bar', 1), ('baz', 4), ('foo', 1)]
>>> sorted(a, key = itemgetter(0, 1))
[('bar', 1), ('bar', 2), ('bar', 3), ('baz', 4), ('foo', 1)]
>>> from bisect import * >>> a = [1, 1, 2, 2, 2, 3, 3, 3, 3, 4] >>> bisect_left(a, 2) 2 >>> bisect(a, 2) 5 >>> insort_left(a, 2) >>> a [1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4] >>> insort(a, 2) >>> a [1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4]
>>> def bsearch(xs, x): ... i = bisect_left(xs, x) ... return len(xs) != i and xs[i] == x ... >>> a [1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4] >>> bsearch(a, 1) True >>> bsearch(a, 2) True >>> bsearch(a, 3) True >>> bsearch(a, 4) True >>> bsearch(a, 5) False >>> bsearch(a, 0) False
問題やプログラム (アルゴリズム) の説明は下記ページを参照してください。
#
# sample04.py : 簡単なプログラム (4)
#
# Copyright (C) 2018 Makoto Hiroi
#
import functools, math
# 最大公約数 (モジュール math に gcd() がある)
# 末尾再帰
def gcd_rec(a, b):
if b == 0: return a
return gcd_rec(b, a % b)
# 繰り返し
def gcd(a, b):
while b > 0:
a, b = b, a % b
return a
# 最小公倍数
def lcm(a, b):
return a * b // gcd(a, b)
print("----- gcd -----")
print(gcd_rec(12345678, 123456789))
print(gcd_rec(1234321, 12345654321))
print(gcd(12345678, 123456789))
print(gcd(1234321, 12345654321))
print(functools.reduce(gcd, [123, 12345, 12345678]))
print("----- lcm -----")
print(lcm(5, 7))
print(lcm(14, 35))
print(functools.reduce(lcm, range(2, 21)))
print(functools.reduce(lcm, range(2, 31)))
# 平方根 (ニュートン法)
def sqrt(x):
def init(x, s = 1.0):
while s < x:
s *= 2.0
x /= 2.0
return s
if x < 0:
raise ValueError('sqrt domain error')
p = init(x) if x > 1.0 else 1.0
while True:
q = (p + x / p) / 2
if q >= p: break
p = q
return p
print('----- sqrt -----')
print(sqrt(0.5))
print(sqrt(2))
print(sqrt(3))
print(sqrt(4))
print(sqrt(5))
print(math.sqrt(0.5))
print(math.sqrt(2))
print(math.sqrt(3))
print(math.sqrt(4))
print(math.sqrt(5))
# めのこ平方
def isqrt(n):
def isqrt_sub(n, m):
while n >= m:
n -= m
m += 2
return m // 2
if n < 100:
return isqrt_sub(n, 1)
else:
m = 10 * isqrt(n // 100)
return isqrt_sub(n - m * m, 2 * m + 1)
print('----- isqrt -----')
print(isqrt(6789))
print(isqrt(123456789))
print(isqrt(1234567890))
#
# 素因数分解
#
def factorization(n):
def factor_sub(n, m):
c = 0
while n % m == 0:
c += 1
n //= m
return c, n
#
buff = []
c, m = factor_sub(n, 2)
if c > 0: buff.append((2, c))
c, m = factor_sub(m, 3)
if c > 0: buff.append((3, c))
x = 5
while m >= x * x:
c, m = factor_sub(m, x)
if c > 0: buff.append((x, c))
if x % 6 == 5:
x += 2
else:
x += 4
if m > 1: buff.append((m, 1))
return buff
#
# 約数の個数
#
def divisor_num(n):
a = 1
for _, x in factorization(n):
a *= x + 1
return a
print('----- divisor_num -----')
print(divisor_num(24))
print(divisor_num(12345678))
print(divisor_num(123456789))
print(divisor_num(1234567890))
print(divisor_num(1111111111))
#
# 約数の合計値
#
# σ(p, n) の計算
def div_sum_sub(p, n):
a = 0
while n > 0:
a += p ** n
n -= 1
return a + 1
def divisor_sum(n):
a = 1
for p, q in factorization(n):
a *= div_sum_sub(p, q)
return a
print('----- divisor_sum -----')
print(divisor_sum(24))
print(divisor_sum(12345678))
print(divisor_sum(123456789))
print(divisor_sum(1234567890))
print(divisor_sum(1111111111))
#
# 約数
#
# p ^ q の約数を求める
def divisor_sub(p, q):
a = []
for i in range(0, q + 1):
a.append(p ** i)
return a
def divisor(n):
xs = factorization(n)
ys = divisor_sub(xs[0][0], xs[0][1])
for p, q in xs[1:]:
ys = [x * y for x in divisor_sub(p, q) for y in ys]
return sorted(ys)
print('----- divisor -----')
print(divisor(24))
print(divisor(12345678))
print(divisor(123456789))
print(divisor(1234567890))
print(divisor(1111111111))
#
# 循環小数
#
# 探索 (リストのメソッド index() は ValueError が送出される)
def position(n, xs):
for i, x in enumerate(xs):
if x == n: return i
return -1
# 循環小数 m/n = ([...],[...])
def repdec(m, n):
xs = []
ys = []
while True:
p = m // n
q = m % n
if q == 0:
ys.append(p)
return ys, [0]
else:
x = position(q, xs)
if x >= 0:
ys.append(p)
return ys[:x+1], ys[x+1:]
xs.append(q)
ys.append(p)
m = q * 10
# 循環小数を分数に直す
def from_repdec(xs, ys):
# 有限小数の部分を分数に直す
p0 = functools.reduce(lambda a, x: a * 10 + x, xs, 0)
q0 = 10 ** (len(xs) - 1)
# 循環節を分数に直す
p1 = functools.reduce(lambda a, x: a * 10 + x, ys, 0)
q1 = (10 ** len(ys) - 1)
# 有限小数 + 循環節
a = q0 * q1
b = q1 * p0 + p1
c = gcd(a, b)
return b // c, a // c
print('----- repdec, from_repdec -----')
for x in range(2, 12):
xs = repdec(1, x)
print(xs)
print(from_repdec(*xs))
xs = repdec(355, 113)
print(xs)
print(from_repdec(*xs))
#
# カッコ列
#
def kakko(f, n):
def kakko_sub(x, y, a):
if x == y == n:
f(a)
else:
if x < n:
kakko_sub(x + 1, y, a + '(')
if y < x:
kakko_sub(x, y + 1, a + ')')
kakko_sub(0, 0, '')
print('----- kakko -----')
kakko(print, 3)
kakko(print, 4)
#
# カタラン数
#
def catalan_num(n):
table = [1] * n
for i in range(1, n):
for j in range(i, n):
table[j] += table[j - 1]
return table[-1]
print('----- Catalan number -----')
for x in range(1, 11):
print(catalan_num(x))
print(catalan_num(50))
print(catalan_num(100))
#
# カッコ列と二分木
#
# 葉
class Leaf:
def __repr__(self): return 'Leaf'
# 節
class Node:
def __init__(self, l, r):
self.left = l
self.right = r
def __repr__(self):
return 'Node({}, {})'.format(self.left, self.right)
# 二分木をカッコ列に変換
def kakko_from_tree(tree):
def sub(tree):
if isinstance(tree, Leaf):
return ')'
else:
return '(' + sub(tree.left) + sub(tree.right)
s = sub(tree)
return s[:-1]
# カッコ列を二分木に変換
def kakko_to_tree(s):
def sub(i):
if len(s) <= i:
return Leaf(), i
elif s[i] == ')':
return Leaf(), i + 1
elif s[i] == '(':
l, j = sub(i + 1)
r, k = sub(j)
return Node(l, r), k
else:
raise Exception('kakko_to_tree: illegal char')
return sub(0)[0]
def test(s):
print(s)
t = kakko_to_tree(s)
print(t)
u = kakko_from_tree(t)
print(u)
print('----- kakko to tree, kakko from tree -----')
kakko(test, 3)
#
# 分割数
#
def part_num(n, k):
if n == 1 or k == 1:
return 1
if n < 0 or k < 1:
return 0
else:
return part_num(n - k, k) + part_num(n, k - 1)
def partition_number(n):
return part_num(n, n)
# 動的法による高速化
def partition_number_fast(n):
table = [1] * (n + 1)
for k in range(2, n + 1):
for m in range(k, n + 1):
table[m] += table[m - k]
return table[n]
# 整数の分割
def part_int_sub(n, k, a):
if n == 0: print(a)
elif n == 1: print(a + [1])
elif k == 1: print(a + [1] * n)
else:
if n >= k:
part_int_sub(n - k, k, a + [k])
part_int_sub(n, k - 1, a)
def partition_of_int(n): part_int_sub(n, n, [])
print('----- partition number -----')
for x in range(1, 11): print(partition_number(x))
print(partition_number_fast(1000))
print(partition_number_fast(2000))
print(partition_number_fast(4000))
partition_of_int(5)
partition_of_int(6)
partition_of_int(7)
#
# 集合の分割
#
def part_sub(f, ls, a):
if not ls:
f(a)
else:
for i in range(len(a)):
a[i].append(ls[0])
part_sub(f, ls[1:], a)
a[i].pop()
a.append([ls[0]])
part_sub(f, ls[1:], a)
a.pop()
def partition_of_set(f, ls):
part_sub(f, ls[1:], [[ls[0]]])
print('----- partition of set -----')
partition_of_set(print, [1,2,3])
partition_of_set(print, [1,2,3, 4])
----- gcd ----- 9 121 9 121 3 ----- lcm ----- 35 70 232792560 2329089562800 ----- sqrt ----- 0.7071067811865475 1.414213562373095 1.7320508075688772 2.0 2.23606797749979 0.7071067811865476 1.4142135623730951 1.7320508075688772 2.0 2.23606797749979 ----- isqrt ----- 82 11111 35136 ----- divisor_num ----- 8 24 12 48 16 ----- divisor_sum ----- 60 27319968 178422816 3211610688 1246404096 ----- divisor ----- [1, 2, 3, 4, 6, 8, 12, 24] [1, 2, 3, 6, 9, 18, 47, 94, 141, 282, 423, 846, 14593, 29186, 43779, 87558, 131337, 262674, 685871, 1371742, 2057613, 4115226, 6172839, 12345678] [1, 3, 9, 3607, 3803, 10821, 11409, 32463, 34227, 13717421, 41152263, 123456789] [1, 2, 3, 5, 6, 9, 10, 15, 18, 30, 45, 90, 3607, 3803, 7214, 7606, 10821, 11409, 18035, 19015, 21642, 22818, 32463, 34227, 36070, 38030, 54105, 57045, 64926, 68454, 108210, 114090, 162315, 171135, 324630, 342270, 13717421, 27434842, 41152263, 68587105, 82304526, 123456789, 137174210, 205761315, 246913578, 411522630, 617283945, 1234567890] [1, 11, 41, 271, 451, 2981, 9091, 11111, 100001, 122221, 372731, 2463661, 4100041, 27100271, 101010101, 1111111111] ----- repdec, from_repdec ----- ([0, 5], [0]) (1, 2) ([0], [3]) (1, 3) ([0, 2, 5], [0]) (1, 4) ([0, 2], [0]) (1, 5) ([0, 1], [6]) (1, 6) ([0], [1, 4, 2, 8, 5, 7]) (1, 7) ([0, 1, 2, 5], [0]) (1, 8) ([0], [1]) (1, 9) ([0, 1], [0]) (1, 10) ([0], [0, 9]) (1, 11) ([3], [1, 4, 1, 5, 9, 2, 9, 2, 0, 3, 5, 3, 9, 8, 2, 3, 0, 0, 8, 8, 4, 9, 5, 5, 7, 5, 2, 2, 1, 2, 3, 8, 9, 3, 8, 0, 5, 3, 0, 9, 7, 3, 4, 5, 1, 3, 2, 7, 4, 3, 3, 6, 2, 8, 3, 1, 8, 5, 8, 4, 0, 7, 0, 7, 9, 6, 4, 6, 0, 1, 7, 6, 9, 9, 1, 1, 5, 0, 4, 4, 2, 4, 7, 7, 8, 7, 6, 1, 0, 6, 1, 9, 4, 6, 9, 0, 2, 6, 5, 4, 8, 6, 7, 2, 5, 6, 6, 3, 7, 1, 6, 8]) (355, 113) ----- kakko ----- ((())) (()()) (())() ()(()) ()()() (((()))) ((()())) ((())()) ((()))() (()(())) (()()()) (()())() (())(()) (())()() ()((())) ()(()()) ()(())() ()()(()) ()()()() ----- Catalan number ----- 1 2 5 14 42 132 429 1430 4862 16796 1978261657756160653623774456 896519947090131496687170070074100632420837521538745909320 ----- kakko to tree, kakko from tree ----- ((())) Node(Node(Node(Leaf, Leaf), Leaf), Leaf) ((())) (()()) Node(Node(Leaf, Node(Leaf, Leaf)), Leaf) (()()) (())() Node(Node(Leaf, Leaf), Node(Leaf, Leaf)) (())() ()(()) Node(Leaf, Node(Node(Leaf, Leaf), Leaf)) ()(()) ()()() Node(Leaf, Node(Leaf, Node(Leaf, Leaf))) ()()() ----- partition number ----- 1 2 3 5 7 11 15 22 30 42 24061467864032622473692149727991 4720819175619413888601432406799959512200344166 1024150064776551375119256307915896842122498030313150910234889093895 [5] [4, 1] [3, 2] [3, 1, 1] [2, 2, 1] [2, 1, 1, 1] [1, 1, 1, 1, 1] [6] [5, 1] [4, 2] [4, 1, 1] [3, 3] [3, 2, 1] [3, 1, 1, 1] [2, 2, 2] [2, 2, 1, 1] [2, 1, 1, 1, 1] [1, 1, 1, 1, 1, 1] [7] [6, 1] [5, 2] [5, 1, 1] [4, 3] [4, 2, 1] [4, 1, 1, 1] [3, 3, 1] [3, 2, 2] [3, 2, 1, 1] [3, 1, 1, 1, 1] [2, 2, 2, 1] [2, 2, 1, 1, 1] [2, 1, 1, 1, 1, 1] [1, 1, 1, 1, 1, 1, 1] ----- partition of set ----- [[1, 2, 3]] [[1, 2], [3]] [[1, 3], [2]] [[1], [2, 3]] [[1], [2], [3]] [[1, 2, 3, 4]] [[1, 2, 3], [4]] [[1, 2, 4], [3]] [[1, 2], [3, 4]] [[1, 2], [3], [4]] [[1, 3, 4], [2]] [[1, 3], [2, 4]] [[1, 3], [2], [4]] [[1, 4], [2, 3]] [[1], [2, 3, 4]] [[1], [2, 3], [4]] [[1, 4], [2], [3]] [[1], [2, 4], [3]] [[1], [2], [3, 4]] [[1], [2], [3], [4]]