This documentation is automatically generated by online-judge-tools/verification-helper
# verification-helper: PROBLEM https://judge.yosupo.jp/problem/aplusb
import pytest
import random
class TestView:
def test_initialization(self):
"""Test basic initialization of view"""
data = [1, 2, 3, 4, 5]
v = view(data, 1, 4)
assert v.A is data
assert v.l == 1
assert v.r == 4
assert len(v) == 3
def test_len(self):
"""Test __len__ method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Test different ranges
assert len(view(data, 0, 5)) == 5
assert len(view(data, 2, 7)) == 5
assert len(view(data, 0, 10)) == 10
assert len(view(data, 5, 5)) == 0 # Empty range
def test_getitem(self):
"""Test __getitem__ method"""
data = [10, 20, 30, 40, 50]
v = view(data, 1, 4) # View of [20, 30, 40]
assert v[0] == 20
assert v[1] == 30
assert v[2] == 40
# Test IndexError for out of bounds
with pytest.raises(IndexError):
v[3]
with pytest.raises(IndexError):
v[-1]
def test_setitem(self):
"""Test __setitem__ method"""
data = [10, 20, 30, 40, 50]
v = view(data, 1, 4) # View of [20, 30, 40]
v[0] = 25
v[1] = 35
v[2] = 45
assert data == [10, 25, 35, 45, 50]
assert v[0] == 25
assert v[1] == 35
assert v[2] == 45
def test_contains(self):
"""Test __contains__ method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert 3 in v
assert 4 in v
assert 5 in v
assert 6 in v
assert 1 not in v # Outside view range
assert 2 not in v # Outside view range
assert 7 not in v # Outside view range
assert 10 not in v # Not in data at all
def test_set_range(self):
"""Test set_range method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
v = view(data, 2, 5)
assert len(v) == 3
assert v[0] == 3
# Change the range
v.set_range(4, 8)
assert len(v) == 4
assert v[0] == 5
assert v[1] == 6
assert v[2] == 7
assert v[3] == 8
def test_index(self):
"""Test index method"""
data = [10, 20, 30, 40, 50, 60, 70]
v = view(data, 2, 6) # View of [30, 40, 50, 60]
assert v.index(30) == 0
assert v.index(40) == 1
assert v.index(50) == 2
assert v.index(60) == 3
# Test ValueError for element not in view
with pytest.raises(ValueError):
v.index(10) # Outside view range
with pytest.raises(ValueError):
v.index(70) # Outside view range
with pytest.raises(ValueError):
v.index(100) # Not in data at all
def test_reverse(self):
"""Test reverse method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 7) # View of [3, 4, 5, 6, 7]
v.reverse()
# Check that the view is reversed
assert v[0] == 7
assert v[1] == 6
assert v[2] == 5
assert v[3] == 4
assert v[4] == 3
# Check that the underlying array is modified
assert data == [1, 2, 7, 6, 5, 4, 3, 8, 9]
def test_sort(self):
"""Test sort method"""
data = [1, 5, 2, 8, 3, 9, 4, 6, 7]
v = view(data, 2, 7) # View of [2, 8, 3, 9, 4]
v.sort()
# Check that the view is sorted
assert v[0] == 2
assert v[1] == 3
assert v[2] == 4
assert v[3] == 8
assert v[4] == 9
# Check that the underlying array is modified correctly
assert data == [1, 5, 2, 3, 4, 8, 9, 6, 7]
def test_sort_with_parameters(self):
"""Test sort method with reverse parameter"""
data = [1, 5, 2, 8, 3, 9, 4, 6, 7]
v = view(data, 2, 7) # View of [2, 8, 3, 9, 4]
v.sort(reverse=True)
# Check that the view is sorted in reverse
assert v[0] == 9
assert v[1] == 8
assert v[2] == 4
assert v[3] == 3
assert v[4] == 2
# Check that the underlying array is modified correctly
assert data == [1, 5, 9, 8, 4, 3, 2, 6, 7]
def test_pop(self):
"""Test pop method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert len(v) == 4
# Pop from the end
popped = v.pop()
assert popped == 6
assert len(v) == 3
assert v[2] == 5 # Last element is now 5
# Pop again
popped = v.pop()
assert popped == 5
assert len(v) == 2
def test_append(self):
"""Test append method"""
data = [1, 2, 3, 4, 5, 0, 0, 0, 9] # Extra space for appending
v = view(data, 2, 5) # View of [3, 4, 5]
assert len(v) == 3
# Append to the end
v.append(6)
assert len(v) == 4
assert v[3] == 6
assert data[5] == 6 # Check underlying array
# Append again
v.append(7)
assert len(v) == 5
assert v[4] == 7
def test_popleft(self):
"""Test popleft method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert len(v) == 4
# Pop from the beginning
popped = v.popleft()
assert popped == 3
assert len(v) == 3
assert v[0] == 4 # First element is now 4
# Pop again
popped = v.popleft()
assert popped == 4
assert len(v) == 2
assert v[0] == 5
def test_appendleft(self):
"""Test appendleft method"""
data = [0, 0, 1, 2, 3, 4, 5, 6, 7] # Extra space at beginning
v = view(data, 4, 7) # View of [3, 4, 5]
assert len(v) == 3
assert v[0] == 3
# Append to the beginning
v.appendleft(2)
assert len(v) == 4
assert v[0] == 2
assert v[1] == 3
assert data[3] == 2 # Check underlying array
# Append again
v.appendleft(1)
assert len(v) == 5
assert v[0] == 1
assert v[1] == 2
def test_validate(self):
"""Test validate method"""
data = [1, 2, 3, 4, 5]
# Valid ranges
v1 = view(data, 0, 5)
assert v1.validate() == True
v2 = view(data, 2, 4)
assert v2.validate() == True
v3 = view(data, 3, 3) # Empty range
assert v3.validate() == True
# Invalid ranges
v4 = view(data, -1, 3)
assert v4.validate() == False
v5 = view(data, 2, 6) # r > len(A)
assert v5.validate() == False
v6 = view(data, 3, 2) # l > r
assert v6.validate() == False
def test_empty_view(self):
"""Test operations on empty view"""
data = [1, 2, 3, 4, 5]
v = view(data, 3, 3) # Empty view
assert len(v) == 0
# Test that operations on empty view behave correctly
with pytest.raises(IndexError):
v[0]
assert 1 not in v
assert 3 not in v
def test_edge_cases(self):
"""Test edge cases"""
# Single element view
data = [10, 20, 30, 40, 50]
v = view(data, 2, 3) # View of [30]
assert len(v) == 1
assert v[0] == 30
assert 30 in v
assert 20 not in v
# Modify single element
v[0] = 35
assert data == [10, 20, 35, 40, 50]
def test_view_operations_sequence(self):
"""Test a sequence of operations"""
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
v = view(data, 2, 8) # View of [30, 40, 50, 60, 70, 80]
# Initial state
assert len(v) == 6
assert v[0] == 30
assert v[5] == 80
# Modify some elements
v[1] = 45
v[3] = 65
assert data[3] == 45
assert data[5] == 65
# Pop and append
popped = v.pop()
assert popped == 80
assert len(v) == 5
v.append(85)
assert len(v) == 6
assert v[5] == 85
# Reverse
v.reverse()
assert v[0] == 85
assert v[5] == 30
def test_with_different_types(self):
"""Test view with different data types"""
# String data
str_data = ['a', 'b', 'c', 'd', 'e', 'f']
str_view = view(str_data, 1, 4) # ['b', 'c', 'd']
assert len(str_view) == 3
assert str_view[0] == 'b'
assert 'c' in str_view
assert 'a' not in str_view
str_view.sort()
assert str_view[0] == 'b'
assert str_view[1] == 'c'
assert str_view[2] == 'd'
# Float data
float_data = [1.1, 2.2, 3.3, 4.4, 5.5]
float_view = view(float_data, 1, 4) # [2.2, 3.3, 4.4]
assert len(float_view) == 3
assert float_view[1] == 3.3
assert 2.2 in float_view
def test_large_data_operations(self):
"""Test operations on larger datasets"""
# Create large dataset
data = list(range(1000))
v = view(data, 100, 900) # 800 elements
assert len(v) == 800
assert v[0] == 100
assert v[799] == 899
# Test contains on large dataset
assert 500 in v
assert 50 not in v
assert 950 not in v
# Test index on large dataset
assert v.index(200) == 100
assert v.index(600) == 500
def test_random_operations(self):
"""Test random operations for robustness"""
random.seed(42) # For reproducibility
# Create test data
data = list(range(100))
original_data = data.copy()
# Create view
start, end = 20, 80
v = view(data, start, end)
# Perform random operations
for _ in range(50):
op = random.choice(['read', 'write', 'contains'])
if op == 'read' and len(v) > 0:
idx = random.randint(0, len(v) - 1)
val = v[idx]
assert val == data[start + idx]
elif op == 'write' and len(v) > 0:
idx = random.randint(0, len(v) - 1)
new_val = random.randint(1000, 2000)
v[idx] = new_val
assert data[start + idx] == new_val
elif op == 'contains':
search_val = random.choice(original_data)
result = search_val in v
# Verify manually
expected = any(data[i] == search_val for i in range(start, min(start + len(v), len(data))))
assert result == expected
def test_view_modification_boundary_safety(self):
"""Test that view modifications don't affect data outside the view"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
original = data.copy()
v = view(data, 3, 7) # View of [4, 5, 6, 7]
# Modify view
v[0] = 40
v[1] = 50
v[2] = 60
v[3] = 70
# Check that only the view range was modified
assert data[0:3] == original[0:3] # Before view unchanged
assert data[7:] == original[7:] # After view unchanged
assert data[3:7] == [40, 50, 60, 70] # View range changed
from cp_library.ds.view.view_cls import view
if __name__ == '__main__':
from cp_library.test.unittest_helper import run_verification_helper_unittest
run_verification_helper_unittest()
# verification-helper: PROBLEM https://judge.yosupo.jp/problem/aplusb
import pytest
import random
class TestView:
def test_initialization(self):
"""Test basic initialization of view"""
data = [1, 2, 3, 4, 5]
v = view(data, 1, 4)
assert v.A is data
assert v.l == 1
assert v.r == 4
assert len(v) == 3
def test_len(self):
"""Test __len__ method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Test different ranges
assert len(view(data, 0, 5)) == 5
assert len(view(data, 2, 7)) == 5
assert len(view(data, 0, 10)) == 10
assert len(view(data, 5, 5)) == 0 # Empty range
def test_getitem(self):
"""Test __getitem__ method"""
data = [10, 20, 30, 40, 50]
v = view(data, 1, 4) # View of [20, 30, 40]
assert v[0] == 20
assert v[1] == 30
assert v[2] == 40
# Test IndexError for out of bounds
with pytest.raises(IndexError):
v[3]
with pytest.raises(IndexError):
v[-1]
def test_setitem(self):
"""Test __setitem__ method"""
data = [10, 20, 30, 40, 50]
v = view(data, 1, 4) # View of [20, 30, 40]
v[0] = 25
v[1] = 35
v[2] = 45
assert data == [10, 25, 35, 45, 50]
assert v[0] == 25
assert v[1] == 35
assert v[2] == 45
def test_contains(self):
"""Test __contains__ method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert 3 in v
assert 4 in v
assert 5 in v
assert 6 in v
assert 1 not in v # Outside view range
assert 2 not in v # Outside view range
assert 7 not in v # Outside view range
assert 10 not in v # Not in data at all
def test_set_range(self):
"""Test set_range method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
v = view(data, 2, 5)
assert len(v) == 3
assert v[0] == 3
# Change the range
v.set_range(4, 8)
assert len(v) == 4
assert v[0] == 5
assert v[1] == 6
assert v[2] == 7
assert v[3] == 8
def test_index(self):
"""Test index method"""
data = [10, 20, 30, 40, 50, 60, 70]
v = view(data, 2, 6) # View of [30, 40, 50, 60]
assert v.index(30) == 0
assert v.index(40) == 1
assert v.index(50) == 2
assert v.index(60) == 3
# Test ValueError for element not in view
with pytest.raises(ValueError):
v.index(10) # Outside view range
with pytest.raises(ValueError):
v.index(70) # Outside view range
with pytest.raises(ValueError):
v.index(100) # Not in data at all
def test_reverse(self):
"""Test reverse method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 7) # View of [3, 4, 5, 6, 7]
v.reverse()
# Check that the view is reversed
assert v[0] == 7
assert v[1] == 6
assert v[2] == 5
assert v[3] == 4
assert v[4] == 3
# Check that the underlying array is modified
assert data == [1, 2, 7, 6, 5, 4, 3, 8, 9]
def test_sort(self):
"""Test sort method"""
data = [1, 5, 2, 8, 3, 9, 4, 6, 7]
v = view(data, 2, 7) # View of [2, 8, 3, 9, 4]
v.sort()
# Check that the view is sorted
assert v[0] == 2
assert v[1] == 3
assert v[2] == 4
assert v[3] == 8
assert v[4] == 9
# Check that the underlying array is modified correctly
assert data == [1, 5, 2, 3, 4, 8, 9, 6, 7]
def test_sort_with_parameters(self):
"""Test sort method with reverse parameter"""
data = [1, 5, 2, 8, 3, 9, 4, 6, 7]
v = view(data, 2, 7) # View of [2, 8, 3, 9, 4]
v.sort(reverse=True)
# Check that the view is sorted in reverse
assert v[0] == 9
assert v[1] == 8
assert v[2] == 4
assert v[3] == 3
assert v[4] == 2
# Check that the underlying array is modified correctly
assert data == [1, 5, 9, 8, 4, 3, 2, 6, 7]
def test_pop(self):
"""Test pop method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert len(v) == 4
# Pop from the end
popped = v.pop()
assert popped == 6
assert len(v) == 3
assert v[2] == 5 # Last element is now 5
# Pop again
popped = v.pop()
assert popped == 5
assert len(v) == 2
def test_append(self):
"""Test append method"""
data = [1, 2, 3, 4, 5, 0, 0, 0, 9] # Extra space for appending
v = view(data, 2, 5) # View of [3, 4, 5]
assert len(v) == 3
# Append to the end
v.append(6)
assert len(v) == 4
assert v[3] == 6
assert data[5] == 6 # Check underlying array
# Append again
v.append(7)
assert len(v) == 5
assert v[4] == 7
def test_popleft(self):
"""Test popleft method"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
v = view(data, 2, 6) # View of [3, 4, 5, 6]
assert len(v) == 4
# Pop from the beginning
popped = v.popleft()
assert popped == 3
assert len(v) == 3
assert v[0] == 4 # First element is now 4
# Pop again
popped = v.popleft()
assert popped == 4
assert len(v) == 2
assert v[0] == 5
def test_appendleft(self):
"""Test appendleft method"""
data = [0, 0, 1, 2, 3, 4, 5, 6, 7] # Extra space at beginning
v = view(data, 4, 7) # View of [3, 4, 5]
assert len(v) == 3
assert v[0] == 3
# Append to the beginning
v.appendleft(2)
assert len(v) == 4
assert v[0] == 2
assert v[1] == 3
assert data[3] == 2 # Check underlying array
# Append again
v.appendleft(1)
assert len(v) == 5
assert v[0] == 1
assert v[1] == 2
def test_validate(self):
"""Test validate method"""
data = [1, 2, 3, 4, 5]
# Valid ranges
v1 = view(data, 0, 5)
assert v1.validate() == True
v2 = view(data, 2, 4)
assert v2.validate() == True
v3 = view(data, 3, 3) # Empty range
assert v3.validate() == True
# Invalid ranges
v4 = view(data, -1, 3)
assert v4.validate() == False
v5 = view(data, 2, 6) # r > len(A)
assert v5.validate() == False
v6 = view(data, 3, 2) # l > r
assert v6.validate() == False
def test_empty_view(self):
"""Test operations on empty view"""
data = [1, 2, 3, 4, 5]
v = view(data, 3, 3) # Empty view
assert len(v) == 0
# Test that operations on empty view behave correctly
with pytest.raises(IndexError):
v[0]
assert 1 not in v
assert 3 not in v
def test_edge_cases(self):
"""Test edge cases"""
# Single element view
data = [10, 20, 30, 40, 50]
v = view(data, 2, 3) # View of [30]
assert len(v) == 1
assert v[0] == 30
assert 30 in v
assert 20 not in v
# Modify single element
v[0] = 35
assert data == [10, 20, 35, 40, 50]
def test_view_operations_sequence(self):
"""Test a sequence of operations"""
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
v = view(data, 2, 8) # View of [30, 40, 50, 60, 70, 80]
# Initial state
assert len(v) == 6
assert v[0] == 30
assert v[5] == 80
# Modify some elements
v[1] = 45
v[3] = 65
assert data[3] == 45
assert data[5] == 65
# Pop and append
popped = v.pop()
assert popped == 80
assert len(v) == 5
v.append(85)
assert len(v) == 6
assert v[5] == 85
# Reverse
v.reverse()
assert v[0] == 85
assert v[5] == 30
def test_with_different_types(self):
"""Test view with different data types"""
# String data
str_data = ['a', 'b', 'c', 'd', 'e', 'f']
str_view = view(str_data, 1, 4) # ['b', 'c', 'd']
assert len(str_view) == 3
assert str_view[0] == 'b'
assert 'c' in str_view
assert 'a' not in str_view
str_view.sort()
assert str_view[0] == 'b'
assert str_view[1] == 'c'
assert str_view[2] == 'd'
# Float data
float_data = [1.1, 2.2, 3.3, 4.4, 5.5]
float_view = view(float_data, 1, 4) # [2.2, 3.3, 4.4]
assert len(float_view) == 3
assert float_view[1] == 3.3
assert 2.2 in float_view
def test_large_data_operations(self):
"""Test operations on larger datasets"""
# Create large dataset
data = list(range(1000))
v = view(data, 100, 900) # 800 elements
assert len(v) == 800
assert v[0] == 100
assert v[799] == 899
# Test contains on large dataset
assert 500 in v
assert 50 not in v
assert 950 not in v
# Test index on large dataset
assert v.index(200) == 100
assert v.index(600) == 500
def test_random_operations(self):
"""Test random operations for robustness"""
random.seed(42) # For reproducibility
# Create test data
data = list(range(100))
original_data = data.copy()
# Create view
start, end = 20, 80
v = view(data, start, end)
# Perform random operations
for _ in range(50):
op = random.choice(['read', 'write', 'contains'])
if op == 'read' and len(v) > 0:
idx = random.randint(0, len(v) - 1)
val = v[idx]
assert val == data[start + idx]
elif op == 'write' and len(v) > 0:
idx = random.randint(0, len(v) - 1)
new_val = random.randint(1000, 2000)
v[idx] = new_val
assert data[start + idx] == new_val
elif op == 'contains':
search_val = random.choice(original_data)
result = search_val in v
# Verify manually
expected = any(data[i] == search_val for i in range(start, min(start + len(v), len(data))))
assert result == expected
def test_view_modification_boundary_safety(self):
"""Test that view modifications don't affect data outside the view"""
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
original = data.copy()
v = view(data, 3, 7) # View of [4, 5, 6, 7]
# Modify view
v[0] = 40
v[1] = 50
v[2] = 60
v[3] = 70
# Check that only the view range was modified
assert data[0:3] == original[0:3] # Before view unchanged
assert data[7:] == original[7:] # After view unchanged
assert data[3:7] == [40, 50, 60, 70] # View range changed
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
from typing import Generic
from typing import TypeVar
_S = TypeVar('S')
_T = TypeVar('T')
_U = TypeVar('U')
import sys
def list_find(lst: list, value, start = 0, stop = sys.maxsize):
try:
return lst.index(value, start, stop)
except:
return -1
class view(Generic[_T]):
__slots__ = 'A', 'l', 'r'
def __init__(V, A: list[_T], l: int, r: int): V.A, V.l, V.r = A, l, r
def __len__(V): return V.r - V.l
def __getitem__(V, i: int):
if 0 <= i < V.r - V.l: return V.A[V.l+i]
else: raise IndexError
def __setitem__(V, i: int, v: _T): V.A[V.l+i] = v
def __contains__(V, v: _T): return list_find(V.A, v, V.l, V.r) != -1
def set_range(V, l: int, r: int): V.l, V.r = l, r
def index(V, v: _T): return V.A.index(v, V.l, V.r) - V.l
def reverse(V):
l, r = V.l, V.r-1
while l < r: V.A[l], V.A[r] = V.A[r], V.A[l]; l += 1; r -= 1
def sort(V, /, *args, **kwargs):
A = V.A[V.l:V.r]; A.sort(*args, **kwargs)
for i,a in enumerate(A,V.l): V.A[i] = a
def pop(V): V.r -= 1; return V.A[V.r]
def append(V, v: _T): V.A[V.r] = v; V.r += 1
def popleft(V): V.l += 1; return V.A[V.l-1]
def appendleft(V, v: _T): V.l -= 1; V.A[V.l] = v;
def validate(V): return 0 <= V.l <= V.r <= len(V.A)
if __name__ == '__main__':
"""
Helper for making unittest files compatible with verification-helper.
This module provides a helper function to run a dummy Library Checker test
so that unittest files can be verified by oj-verify.
"""
def run_verification_helper_unittest():
"""
Run a dummy Library Checker test for verification-helper compatibility.
This function should be called in the __main__ block of unittest files
that need to be compatible with verification-helper.
The function:
1. Reads A and B from input
2. Writes A+B to output
3. If the result is the expected value (1198300249), runs pytest
4. Exits with the pytest result code
"""
from typing import Type, Union, overload
import typing
from collections import deque
from numbers import Number
from types import GenericAlias
from typing import Callable, Collection, Iterator, Union
import os
from io import BytesIO, IOBase
class FastIO(IOBase):
BUFSIZE = 8192
newlines = 0
def __init__(self, file):
self._fd = file.fileno()
self.buffer = BytesIO()
self.writable = "x" in file.mode or "r" not in file.mode
self.write = self.buffer.write if self.writable else None
def read(self):
BUFSIZE = self.BUFSIZE
while True:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
if not b: break
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines = 0
return self.buffer.read()
def readline(self):
BUFSIZE = self.BUFSIZE
while self.newlines == 0:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
self.newlines = b.count(b"\n") + (not b)
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines -= 1
return self.buffer.readline()
def flush(self):
if self.writable:
os.write(self._fd, self.buffer.getvalue())
self.buffer.truncate(0), self.buffer.seek(0)
class IOWrapper(IOBase):
stdin: 'IOWrapper' = None
stdout: 'IOWrapper' = None
def __init__(self, file):
self.buffer = FastIO(file)
self.flush = self.buffer.flush
self.writable = self.buffer.writable
def write(self, s):
return self.buffer.write(s.encode("ascii"))
def read(self):
return self.buffer.read().decode("ascii")
def readline(self):
return self.buffer.readline().decode("ascii")
try:
sys.stdin = IOWrapper.stdin = IOWrapper(sys.stdin)
sys.stdout = IOWrapper.stdout = IOWrapper(sys.stdout)
except:
pass
class TokenStream(Iterator):
stream = IOWrapper.stdin
def __init__(self):
self.queue = deque()
def __next__(self):
if not self.queue: self.queue.extend(self._line())
return self.queue.popleft()
def wait(self):
if not self.queue: self.queue.extend(self._line())
while self.queue: yield
def _line(self):
return TokenStream.stream.readline().split()
def line(self):
if self.queue:
A = list(self.queue)
self.queue.clear()
return A
return self._line()
TokenStream.default = TokenStream()
class CharStream(TokenStream):
def _line(self):
return TokenStream.stream.readline().rstrip()
CharStream.default = CharStream()
ParseFn = Callable[[TokenStream],_T]
class Parser:
def __init__(self, spec: Union[type[_T],_T]):
self.parse = Parser.compile(spec)
def __call__(self, ts: TokenStream) -> _T:
return self.parse(ts)
@staticmethod
def compile_type(cls: type[_T], args = ()) -> _T:
if issubclass(cls, Parsable):
return cls.compile(*args)
elif issubclass(cls, (Number, str)):
def parse(ts: TokenStream): return cls(next(ts))
return parse
elif issubclass(cls, tuple):
return Parser.compile_tuple(cls, args)
elif issubclass(cls, Collection):
return Parser.compile_collection(cls, args)
elif callable(cls):
def parse(ts: TokenStream):
return cls(next(ts))
return parse
else:
raise NotImplementedError()
@staticmethod
def compile(spec: Union[type[_T],_T]=int) -> ParseFn[_T]:
if isinstance(spec, (type, GenericAlias)):
cls = typing.get_origin(spec) or spec
args = typing.get_args(spec) or tuple()
return Parser.compile_type(cls, args)
elif isinstance(offset := spec, Number):
cls = type(spec)
def parse(ts: TokenStream): return cls(next(ts)) + offset
return parse
elif isinstance(args := spec, tuple):
return Parser.compile_tuple(type(spec), args)
elif isinstance(args := spec, Collection):
return Parser.compile_collection(type(spec), args)
elif isinstance(fn := spec, Callable):
def parse(ts: TokenStream): return fn(next(ts))
return parse
else:
raise NotImplementedError()
@staticmethod
def compile_line(cls: _T, spec=int) -> ParseFn[_T]:
if spec is int:
fn = Parser.compile(spec)
def parse(ts: TokenStream): return cls([int(token) for token in ts.line()])
return parse
else:
fn = Parser.compile(spec)
def parse(ts: TokenStream): return cls([fn(ts) for _ in ts.wait()])
return parse
@staticmethod
def compile_repeat(cls: _T, spec, N) -> ParseFn[_T]:
fn = Parser.compile(spec)
def parse(ts: TokenStream): return cls([fn(ts) for _ in range(N)])
return parse
@staticmethod
def compile_children(cls: _T, specs) -> ParseFn[_T]:
fns = tuple((Parser.compile(spec) for spec in specs))
def parse(ts: TokenStream): return cls([fn(ts) for fn in fns])
return parse
@staticmethod
def compile_tuple(cls: type[_T], specs) -> ParseFn[_T]:
if isinstance(specs, (tuple,list)) and len(specs) == 2 and specs[1] is ...:
return Parser.compile_line(cls, specs[0])
else:
return Parser.compile_children(cls, specs)
@staticmethod
def compile_collection(cls, specs):
if not specs or len(specs) == 1 or isinstance(specs, set):
return Parser.compile_line(cls, *specs)
elif (isinstance(specs, (tuple,list)) and len(specs) == 2 and isinstance(specs[1], int)):
return Parser.compile_repeat(cls, specs[0], specs[1])
else:
raise NotImplementedError()
class Parsable:
@classmethod
def compile(cls):
def parser(ts: TokenStream): return cls(next(ts))
return parser
@classmethod
def __class_getitem__(cls, item):
return GenericAlias(cls, item)
@overload
def read() -> list[int]: ...
@overload
def read(spec: Type[_T], char=False) -> _T: ...
@overload
def read(spec: _U, char=False) -> _U: ...
@overload
def read(*specs: Type[_T], char=False) -> tuple[_T, ...]: ...
@overload
def read(*specs: _U, char=False) -> tuple[_U, ...]: ...
def read(*specs: Union[Type[_T],_U], char=False):
if not char and not specs: return [int(s) for s in TokenStream.default.line()]
parser: _T = Parser.compile(specs[0] if len(specs) == 1 else specs)
return parser(CharStream.default if char else TokenStream.default)
import os
from io import BytesIO, IOBase
class FastIO(IOBase):
BUFSIZE = 8192
newlines = 0
def __init__(self, file):
self._fd = file.fileno()
self.buffer = BytesIO()
self.writable = "x" in file.mode or "r" not in file.mode
self.write = self.buffer.write if self.writable else None
def read(self):
BUFSIZE = self.BUFSIZE
while True:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
if not b: break
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines = 0
return self.buffer.read()
def readline(self):
BUFSIZE = self.BUFSIZE
while self.newlines == 0:
b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
self.newlines = b.count(b"\n") + (not b)
ptr = self.buffer.tell()
self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr)
self.newlines -= 1
return self.buffer.readline()
def flush(self):
if self.writable:
os.write(self._fd, self.buffer.getvalue())
self.buffer.truncate(0), self.buffer.seek(0)
class IOWrapper(IOBase):
stdin: 'IOWrapper' = None
stdout: 'IOWrapper' = None
def __init__(self, file):
self.buffer = FastIO(file)
self.flush = self.buffer.flush
self.writable = self.buffer.writable
def write(self, s):
return self.buffer.write(s.encode("ascii"))
def read(self):
return self.buffer.read().decode("ascii")
def readline(self):
return self.buffer.readline().decode("ascii")
try:
sys.stdin = IOWrapper.stdin = IOWrapper(sys.stdin)
sys.stdout = IOWrapper.stdout = IOWrapper(sys.stdout)
except:
pass
def write(*args, **kwargs):
'''Prints the values to a stream, or to stdout_fast by default.'''
sep, file = kwargs.pop("sep", " "), kwargs.pop("file", IOWrapper.stdout)
at_start = True
for x in args:
if not at_start:
file.write(sep)
file.write(str(x))
at_start = False
file.write(kwargs.pop("end", "\n"))
if kwargs.pop("flush", False):
file.flush()
A, B = read()
write(C := A + B)
if C != 1198300249:
sys.exit(0)
import io
from contextlib import redirect_stdout, redirect_stderr
# Capture all output during test execution
output = io.StringIO()
with redirect_stdout(output), redirect_stderr(output):
# Get the calling module's file path
frame = sys._getframe(1)
test_file = frame.f_globals.get('__file__')
if test_file is None:
test_file = sys.argv[0]
result = pytest.main([test_file])
if result != 0:
print(output.getvalue())
sys.exit(result)
run_verification_helper_unittest()