commit
fa26344cd0
29 changed files with 19850 additions and 100 deletions
8
.github/workflows/quality.yml
vendored
8
.github/workflows/quality.yml
vendored
|
|
@ -90,7 +90,7 @@ jobs:
|
|||
- name: Install ruff
|
||||
run: uv tool install ruff
|
||||
- name: Check Python formatting with ruff
|
||||
run: ruff format --check scrapers/ tests/scrapers/
|
||||
run: ruff format --check .
|
||||
|
||||
python-lint:
|
||||
name: Python Lint Check
|
||||
|
|
@ -104,7 +104,7 @@ jobs:
|
|||
- name: Install ruff
|
||||
run: uv tool install ruff
|
||||
- name: Lint Python files with ruff
|
||||
run: ruff check scripts/ scrapers/ tests/scrapers/
|
||||
run: ruff check .
|
||||
|
||||
python-typecheck:
|
||||
name: Python Type Check
|
||||
|
|
@ -118,7 +118,7 @@ jobs:
|
|||
- name: Install dependencies with mypy
|
||||
run: uv sync --dev
|
||||
- name: Type check Python files with mypy
|
||||
run: uv run mypy scripts/ scrapers/ tests/scrapers/
|
||||
run: uv run mypy .
|
||||
|
||||
markdown-format:
|
||||
name: Markdown Format Check
|
||||
|
|
@ -138,4 +138,4 @@ jobs:
|
|||
- name: Install prettier
|
||||
run: pnpm add -g prettier@3.1.0
|
||||
- name: Check markdown formatting with prettier
|
||||
run: prettier --check "*.md" "docs/**/*.md" || true
|
||||
run: prettier --check .
|
||||
|
|
|
|||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
python:
|
||||
- 'scripts/**'
|
||||
- 'scrapers/**'
|
||||
- 'tests/scrapers/**'
|
||||
- 'tests/**'
|
||||
- 'pyproject.toml'
|
||||
- 'uv.lock'
|
||||
|
||||
|
|
@ -64,4 +64,4 @@ jobs:
|
|||
- name: Fetch camoufox data
|
||||
run: uv run camoufox fetch
|
||||
- name: Run Python tests
|
||||
run: uv run pytest tests/scrapers/ -v
|
||||
run: uv run pytest tests/ -v
|
||||
|
|
|
|||
|
|
@ -1,35 +1,38 @@
|
|||
minimum_pre_commit_version: "3.5.0"
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/JohnnyMorganz/StyLua
|
||||
rev: v2.1.0
|
||||
hooks:
|
||||
- id: stylua-github
|
||||
name: stylua (Lua formatter)
|
||||
args: ["."]
|
||||
files: ^(lua/|spec/|plugin/|after/|ftdetect/|.*\.lua$)
|
||||
additional_dependencies: []
|
||||
files: \.lua$
|
||||
pass_filenames: true
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.9
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
name: ruff (format)
|
||||
files: ^(scrapers/|tests/scrapers/|.*\.py$)
|
||||
files: \.py$
|
||||
- id: ruff
|
||||
name: ruff (lint)
|
||||
name: ruff (lint imports)
|
||||
args: ["--fix", "--select=I"]
|
||||
files: ^(scrapers/|tests/scrapers/|.*\.py$)
|
||||
files: \.py$
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy
|
||||
name: mypy (type check)
|
||||
entry: uv run mypy
|
||||
language: system
|
||||
args: ["scrapers/", "tests/scrapers/"]
|
||||
files: ^(scrapers/|tests/scrapers/|.*\.py$)
|
||||
args: ["."]
|
||||
pass_filenames: false
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.1.0
|
||||
hooks:
|
||||
- id: prettier
|
||||
name: prettier (format markdown)
|
||||
files: \.(md)$
|
||||
files: \.md$
|
||||
|
||||
|
|
|
|||
17
.prettierrc
Normal file
17
.prettierrc
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"proseWrap": "always",
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"trailingComma": "none",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.md"],
|
||||
"options": {
|
||||
"parser": "markdown"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -153,9 +153,7 @@ function M.handle_command(opts)
|
|||
cache_commands.handle_cache_command(cmd)
|
||||
elseif cmd.type == 'contest_setup' then
|
||||
local setup = require('cp.setup')
|
||||
if setup.set_platform(cmd.platform) then
|
||||
setup.setup_contest(cmd.platform, cmd.contest, nil)
|
||||
end
|
||||
setup.setup_contest(cmd.platform, cmd.contest, nil)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,16 +7,6 @@ local scraper = require('cp.scraper')
|
|||
local state = require('cp.state')
|
||||
|
||||
local constants = require('cp.constants')
|
||||
local platforms = constants.PLATFORMS
|
||||
|
||||
function M.set_platform(platform)
|
||||
if not vim.tbl_contains(platforms, platform) then
|
||||
logger.log(("Unknown platform '%s'"):format(platform), vim.log.levels.ERROR)
|
||||
return false
|
||||
end
|
||||
state.set_platform(platform)
|
||||
return true
|
||||
end
|
||||
|
||||
---@class TestCaseLite
|
||||
---@field input string
|
||||
|
|
@ -35,9 +25,10 @@ end
|
|||
|
||||
---@param platform string
|
||||
---@param contest_id string
|
||||
---@param problem_id string|nil
|
||||
---@param language? string|nil
|
||||
---@param problem_id? string
|
||||
---@param language? string
|
||||
function M.setup_contest(platform, contest_id, problem_id, language)
|
||||
state.set_platform(platform)
|
||||
state.set_contest_id(contest_id)
|
||||
cache.load()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ dependencies = [
|
|||
"curl-cffi>=0.13.0",
|
||||
"httpx>=0.28.1",
|
||||
"ndjson>=0.3.1",
|
||||
"pydantic>=2.11.10",
|
||||
"requests>=2.32.5",
|
||||
"scrapling[fetchers]>=0.3.5",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import json
|
|||
import re
|
||||
import sys
|
||||
import time
|
||||
from dataclasses import asdict
|
||||
from typing import Any
|
||||
|
||||
import backoff
|
||||
|
|
@ -231,16 +230,12 @@ def _scrape_problem_page_sync(contest_id: str, slug: str) -> dict[str, Any]:
|
|||
|
||||
def _to_problem_summaries(rows: list[dict[str, str]]) -> list[ProblemSummary]:
|
||||
out: list[ProblemSummary] = []
|
||||
seen: set[str] = set()
|
||||
for r in rows:
|
||||
letter = (r.get("letter") or "").strip().upper()
|
||||
title = r.get("title") or ""
|
||||
if not letter:
|
||||
continue
|
||||
pid = letter.lower()
|
||||
if pid in seen:
|
||||
continue
|
||||
seen.add(pid)
|
||||
out.append(ProblemSummary(id=pid, name=title))
|
||||
return out
|
||||
|
||||
|
|
@ -341,7 +336,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: atcoder.py metadata <contest_id> OR atcoder.py tests <contest_id> OR atcoder.py contests",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
mode: str = sys.argv[1]
|
||||
|
|
@ -352,11 +347,11 @@ async def main_async() -> int:
|
|||
result = MetadataResult(
|
||||
success=False, error="Usage: atcoder.py metadata <contest_id>"
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
contest_id = sys.argv[2]
|
||||
result = await scraper.scrape_contest_metadata(contest_id)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 0 if result.success else 1
|
||||
|
||||
if mode == "tests":
|
||||
|
|
@ -370,7 +365,7 @@ async def main_async() -> int:
|
|||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
)
|
||||
print(json.dumps(asdict(tests_result)))
|
||||
print(tests_result.model_dump_json())
|
||||
return 1
|
||||
contest_id = sys.argv[2]
|
||||
await scraper.stream_tests_for_category_async(contest_id)
|
||||
|
|
@ -381,17 +376,17 @@ async def main_async() -> int:
|
|||
contest_result = ContestListResult(
|
||||
success=False, error="Usage: atcoder.py contests"
|
||||
)
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 1
|
||||
contest_result = await scraper.scrape_contest_list()
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 0 if contest_result.success else 1
|
||||
|
||||
result = MetadataResult(
|
||||
success=False,
|
||||
error="Unknown mode. Use 'metadata <contest_id>', 'tests <contest_id>', or 'contests'",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Awaitable, Callable, ParamSpec, cast
|
||||
|
||||
from .models import ContestListResult, MetadataResult, TestsResult
|
||||
|
|
@ -9,14 +6,6 @@ from .models import ContestListResult, MetadataResult, TestsResult
|
|||
P = ParamSpec("P")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ScraperConfig:
|
||||
timeout_seconds: int = 30
|
||||
max_retries: int = 3
|
||||
backoff_base: float = 2.0
|
||||
rate_limit_delay: float = 1.0
|
||||
|
||||
|
||||
class BaseScraper(ABC):
|
||||
@property
|
||||
@abstractmethod
|
||||
|
|
@ -38,6 +27,7 @@ class BaseScraper(ABC):
|
|||
success=False,
|
||||
error=f"{self.platform_name}: {error_msg}",
|
||||
contest_id=contest_id,
|
||||
problems=[],
|
||||
)
|
||||
|
||||
def _create_tests_error(
|
||||
|
|
@ -51,11 +41,14 @@ class BaseScraper(ABC):
|
|||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
interactive=False,
|
||||
)
|
||||
|
||||
def _create_contests_error(self, error_msg: str) -> ContestListResult:
|
||||
return ContestListResult(
|
||||
success=False, error=f"{self.platform_name}: {error_msg}"
|
||||
success=False,
|
||||
error=f"{self.platform_name}: {error_msg}",
|
||||
contests=[],
|
||||
)
|
||||
|
||||
async def _safe_execute(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import json
|
|||
import logging
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import asdict
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
|
|
@ -63,8 +62,6 @@ def _extract_limits(block: Tag) -> tuple[int, float]:
|
|||
|
||||
def _group_lines_by_id(pre: Tag) -> dict[int, list[str]]:
|
||||
groups: dict[int, list[str]] = {}
|
||||
if not isinstance(pre, Tag):
|
||||
return groups
|
||||
for div in pre.find_all("div", class_="test-example-line"):
|
||||
cls = " ".join(div.get("class", []))
|
||||
m = re.search(r"\btest-example-line-(\d+)\b", cls)
|
||||
|
|
@ -182,12 +179,8 @@ def _scrape_contest_problems_sync(contest_id: str) -> list[ProblemSummary]:
|
|||
html = _fetch_problems_html(contest_id)
|
||||
blocks = _parse_all_blocks(html)
|
||||
problems: list[ProblemSummary] = []
|
||||
seen: set[str] = set()
|
||||
for b in blocks:
|
||||
pid = b["letter"].upper()
|
||||
if pid in seen:
|
||||
continue
|
||||
seen.add(pid)
|
||||
problems.append(ProblemSummary(id=pid.lower(), name=b["name"]))
|
||||
return problems
|
||||
|
||||
|
|
@ -267,7 +260,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: codeforces.py metadata <contest_id> OR codeforces.py tests <contest_id> OR codeforces.py contests",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
mode: str = sys.argv[1]
|
||||
|
|
@ -278,11 +271,11 @@ async def main_async() -> int:
|
|||
result = MetadataResult(
|
||||
success=False, error="Usage: codeforces.py metadata <contest_id>"
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
contest_id = sys.argv[2]
|
||||
result = await scraper.scrape_contest_metadata(contest_id)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 0 if result.success else 1
|
||||
|
||||
if mode == "tests":
|
||||
|
|
@ -296,7 +289,7 @@ async def main_async() -> int:
|
|||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
)
|
||||
print(json.dumps(asdict(tests_result)))
|
||||
print(tests_result.model_dump_json())
|
||||
return 1
|
||||
contest_id = sys.argv[2]
|
||||
await scraper.stream_tests_for_category_async(contest_id)
|
||||
|
|
@ -307,17 +300,17 @@ async def main_async() -> int:
|
|||
contest_result = ContestListResult(
|
||||
success=False, error="Usage: codeforces.py contests"
|
||||
)
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 1
|
||||
contest_result = await scraper.scrape_contest_list()
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 0 if contest_result.success else 1
|
||||
|
||||
result = MetadataResult(
|
||||
success=False,
|
||||
error="Unknown mode. Use 'metadata <contest_id>', 'tests <contest_id>', or 'contests'",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import asyncio
|
|||
import json
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import asdict
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
|
@ -20,7 +19,7 @@ from .models import (
|
|||
)
|
||||
|
||||
BASE_URL = "https://cses.fi"
|
||||
INDEX_PATH = "/problemset/list"
|
||||
INDEX_PATH = "/problemset"
|
||||
TASK_PATH = "/problemset/task/{id}"
|
||||
HEADERS = {
|
||||
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
|
|
@ -132,12 +131,17 @@ def parse_category_problems(category_id: str, html: str) -> list[ProblemSummary]
|
|||
return []
|
||||
|
||||
|
||||
def parse_limits(html: str) -> tuple[int, int]:
|
||||
def _extract_problem_info(html: str) -> tuple[int, int, bool]:
|
||||
tm = TIME_RE.search(html)
|
||||
mm = MEM_RE.search(html)
|
||||
t = int(round(float(tm.group(1)) * 1000)) if tm else 0
|
||||
m = int(mm.group(1)) if mm else 0
|
||||
return t, m
|
||||
md = MD_BLOCK_RE.search(html)
|
||||
interactive = False
|
||||
if md:
|
||||
body = md.group(1)
|
||||
interactive = "This is an interactive problem." in body
|
||||
return t, m, interactive
|
||||
|
||||
|
||||
def parse_title(html: str) -> str:
|
||||
|
|
@ -220,10 +224,10 @@ class CSESScraper(BaseScraper):
|
|||
try:
|
||||
html = await fetch_text(client, task_path(pid))
|
||||
tests = parse_tests(html)
|
||||
timeout_ms, memory_mb = parse_limits(html)
|
||||
timeout_ms, memory_mb, interactive = _extract_problem_info(html)
|
||||
except Exception:
|
||||
tests = []
|
||||
timeout_ms, memory_mb = 0, 0
|
||||
timeout_ms, memory_mb, interactive = 0, 0, False
|
||||
return {
|
||||
"problem_id": pid,
|
||||
"tests": [
|
||||
|
|
@ -231,7 +235,7 @@ class CSESScraper(BaseScraper):
|
|||
],
|
||||
"timeout_ms": timeout_ms,
|
||||
"memory_mb": memory_mb,
|
||||
"interactive": False,
|
||||
"interactive": interactive,
|
||||
}
|
||||
|
||||
tasks = [run_one(p.id) for p in problems]
|
||||
|
|
@ -246,7 +250,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: cses.py metadata <category_id> OR cses.py tests <category> OR cses.py contests",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
mode: str = sys.argv[1]
|
||||
|
|
@ -257,11 +261,11 @@ async def main_async() -> int:
|
|||
result = MetadataResult(
|
||||
success=False, error="Usage: cses.py metadata <category_id>"
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
category_id = sys.argv[2]
|
||||
result = await scraper.scrape_contest_metadata(category_id)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 0 if result.success else 1
|
||||
|
||||
if mode == "tests":
|
||||
|
|
@ -275,7 +279,7 @@ async def main_async() -> int:
|
|||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
)
|
||||
print(json.dumps(asdict(tests_result)))
|
||||
print(tests_result.model_dump_json())
|
||||
return 1
|
||||
category = sys.argv[2]
|
||||
await scraper.stream_tests_for_category_async(category)
|
||||
|
|
@ -286,17 +290,17 @@ async def main_async() -> int:
|
|||
contest_result = ContestListResult(
|
||||
success=False, error="Usage: cses.py contests"
|
||||
)
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 1
|
||||
contest_result = await scraper.scrape_contest_list()
|
||||
print(json.dumps(asdict(contest_result)))
|
||||
print(contest_result.model_dump_json())
|
||||
return 0 if contest_result.success else 1
|
||||
|
||||
result = MetadataResult(
|
||||
success=False,
|
||||
error=f"Unknown mode: {mode}. Use 'metadata <category>', 'tests <category>', or 'contests'",
|
||||
)
|
||||
print(json.dumps(asdict(result)))
|
||||
print(result.model_dump_json())
|
||||
return 1
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +1,63 @@
|
|||
from dataclasses import dataclass, field
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
@dataclass
|
||||
class TestCase:
|
||||
class TestCase(BaseModel):
|
||||
input: str
|
||||
expected: str
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
@dataclass
|
||||
class ProblemSummary:
|
||||
|
||||
class ProblemSummary(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
@dataclass
|
||||
class ContestSummary:
|
||||
|
||||
class ContestSummary(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
display_name: str
|
||||
display_name: str | None = None
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ScrapingResult:
|
||||
class ScrapingResult(BaseModel):
|
||||
success: bool
|
||||
error: str
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
@dataclass
|
||||
class MetadataResult(ScrapingResult):
|
||||
contest_id: str = ""
|
||||
problems: list[ProblemSummary] = field(default_factory=list)
|
||||
problems: list[ProblemSummary] = Field(default_factory=list)
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ContestListResult(ScrapingResult):
|
||||
contests: list[ContestSummary] = field(default_factory=list)
|
||||
contests: list[ContestSummary] = Field(default_factory=list)
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
@dataclass
|
||||
class TestsResult(ScrapingResult):
|
||||
problem_id: str
|
||||
url: str
|
||||
tests: list[TestCase]
|
||||
tests: list[TestCase] = Field(default_factory=list)
|
||||
timeout_ms: int
|
||||
memory_mb: float
|
||||
interactive: bool = False
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
class ScraperConfig(BaseModel):
|
||||
timeout_seconds: int = 30
|
||||
max_retries: int = 3
|
||||
backoff_base: float = 2.0
|
||||
rate_limit_delay: float = 1.0
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
|
|
|||
212
tests/conftest.py
Normal file
212
tests/conftest.py
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
import asyncio
|
||||
import importlib.util
|
||||
import io
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
import requests
|
||||
from scrapling import fetchers
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
FIX = Path(__file__).resolve().parent / "fixtures"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fixture_text():
|
||||
def _load(name: str) -> str:
|
||||
p = FIX / name
|
||||
return p.read_text(encoding="utf-8")
|
||||
|
||||
return _load
|
||||
|
||||
|
||||
def _load_scraper_module(module_path: Path, module_name: str):
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
f"scrapers.{module_name}", module_path
|
||||
)
|
||||
if spec is None or spec.loader is None:
|
||||
raise ImportError(f"Cannot load module {module_name}")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[f"scrapers.{module_name}"] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def _capture_stdout(coro):
|
||||
buf = io.StringIO()
|
||||
old = sys.stdout
|
||||
sys.stdout = buf
|
||||
try:
|
||||
rc = asyncio.run(coro)
|
||||
out = buf.getvalue()
|
||||
finally:
|
||||
sys.stdout = old
|
||||
return rc, out
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def run_scraper_offline(fixture_text):
|
||||
def _router_cses(*, path: str | None = None, url: str | None = None) -> str:
|
||||
if not path and not url:
|
||||
raise AssertionError("CSES expects path or url")
|
||||
|
||||
target = path or url
|
||||
if target is None:
|
||||
raise AssertionError(f"No target for CSES (path={path!r}, url={url!r})")
|
||||
|
||||
if target.startswith("https://cses.fi"):
|
||||
target = target.removeprefix("https://cses.fi")
|
||||
|
||||
if target.strip("/") == "problemset":
|
||||
return fixture_text("cses_contests.html")
|
||||
|
||||
if target.startswith("/problemset/task/") or target.startswith(
|
||||
"problemset/task/"
|
||||
):
|
||||
pid = target.rstrip("/").split("/")[-1]
|
||||
return fixture_text(f"cses_task_{pid}.html")
|
||||
|
||||
raise AssertionError(f"No fixture for CSES path={path!r} url={url!r}")
|
||||
|
||||
def _router_atcoder(*, path: str | None = None, url: str | None = None) -> str:
|
||||
if not url:
|
||||
raise AssertionError("AtCoder expects url routing")
|
||||
if "/contests/archive" in url:
|
||||
return fixture_text("atcoder_contests.html")
|
||||
if url.endswith("/tasks"):
|
||||
return fixture_text("atcoder_abc100_tasks.html")
|
||||
if "/tasks/" in url:
|
||||
slug = url.rsplit("/", 1)[-1]
|
||||
return fixture_text(f"atcoder_task_{slug}.html")
|
||||
raise AssertionError(f"No fixture for AtCoder url={url!r}")
|
||||
|
||||
def _router_codeforces(*, path: str | None = None, url: str | None = None) -> str:
|
||||
if not url:
|
||||
raise AssertionError("Codeforces expects url routing")
|
||||
if "/contest/" in url and url.endswith("/problems"):
|
||||
contest_id = url.rstrip("/").split("/")[-2]
|
||||
return fixture_text(f"codeforces_{contest_id}_problems.html")
|
||||
if "/contests" in url and "/problem/" not in url:
|
||||
return fixture_text("codeforces_contests.html")
|
||||
if "/problem/" in url:
|
||||
parts = url.rstrip("/").split("/")
|
||||
contest_id, index = parts[-3], parts[-1]
|
||||
return fixture_text(f"codeforces_{contest_id}_{index}.html")
|
||||
if "/problemset/problem/" in url:
|
||||
parts = url.rstrip("/").split("/")
|
||||
contest_id, index = parts[-2], parts[-1]
|
||||
return fixture_text(f"codeforces_{contest_id}_{index}.html")
|
||||
|
||||
raise AssertionError(f"No fixture for Codeforces url={url!r}")
|
||||
|
||||
def _make_offline_fetches(scraper_name: str):
|
||||
match scraper_name:
|
||||
case "cses":
|
||||
|
||||
async def __offline_fetch_text(client, path: str, **kwargs):
|
||||
html = _router_cses(path=path)
|
||||
return SimpleNamespace(
|
||||
text=html,
|
||||
status_code=200,
|
||||
raise_for_status=lambda: None,
|
||||
)
|
||||
|
||||
return {
|
||||
"__offline_fetch_text": __offline_fetch_text,
|
||||
}
|
||||
|
||||
case "atcoder":
|
||||
|
||||
def __offline_fetch(url: str, *args, **kwargs):
|
||||
html = _router_atcoder(url=url)
|
||||
return html
|
||||
|
||||
async def __offline_get_async(client, url: str, **kwargs):
|
||||
return _router_atcoder(url=url)
|
||||
|
||||
return {
|
||||
"_fetch": __offline_fetch,
|
||||
"_get_async": __offline_get_async,
|
||||
}
|
||||
|
||||
case "codeforces":
|
||||
|
||||
class MockPage:
|
||||
def __init__(self, html: str):
|
||||
self.html_content = html
|
||||
|
||||
def _mock_stealthy_fetch(url: str, **kwargs):
|
||||
return MockPage(_router_codeforces(url=url))
|
||||
|
||||
def _mock_requests_get(url: str, **kwargs):
|
||||
if "api/contest.list" in url:
|
||||
data = {
|
||||
"status": "OK",
|
||||
"result": [
|
||||
{
|
||||
"id": 1550,
|
||||
"name": "Educational Codeforces Round 155 (Rated for Div. 2)",
|
||||
"phase": "FINISHED",
|
||||
},
|
||||
{
|
||||
"id": 1000,
|
||||
"name": "Codeforces Round #1000",
|
||||
"phase": "FINISHED",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
class R:
|
||||
def json(self_inner):
|
||||
return data
|
||||
|
||||
def raise_for_status(self_inner):
|
||||
return None
|
||||
|
||||
return R()
|
||||
raise AssertionError(f"Unexpected requests.get call: {url}")
|
||||
|
||||
return {
|
||||
"StealthyFetcher.fetch": _mock_stealthy_fetch,
|
||||
"requests.get": _mock_requests_get,
|
||||
}
|
||||
|
||||
case _:
|
||||
raise AssertionError(f"Unknown scraper: {scraper_name}")
|
||||
|
||||
def _run(scraper_name: str, mode: str, *args: str):
|
||||
mod_path = ROOT / "scrapers" / f"{scraper_name}.py"
|
||||
ns = _load_scraper_module(mod_path, scraper_name)
|
||||
offline_fetches = _make_offline_fetches(scraper_name)
|
||||
|
||||
if scraper_name == "codeforces":
|
||||
fetchers.StealthyFetcher.fetch = offline_fetches["StealthyFetcher.fetch"] # type: ignore[assignment]
|
||||
requests.get = offline_fetches["requests.get"]
|
||||
elif scraper_name == "atcoder":
|
||||
ns._fetch = offline_fetches["_fetch"]
|
||||
ns._get_async = offline_fetches["_get_async"]
|
||||
elif scraper_name == "cses":
|
||||
httpx.AsyncClient.get = offline_fetches["__offline_fetch_text"] # type: ignore[assignment]
|
||||
|
||||
main_async = getattr(ns, "main_async")
|
||||
assert callable(main_async), f"main_async not found in {scraper_name}"
|
||||
|
||||
argv = [str(mod_path), mode, *args]
|
||||
old_argv = sys.argv
|
||||
sys.argv = argv
|
||||
try:
|
||||
rc, out = _capture_stdout(main_async())
|
||||
finally:
|
||||
sys.argv = old_argv
|
||||
|
||||
json_lines: list[Any] = []
|
||||
for line in (_line for _line in out.splitlines() if _line.strip()):
|
||||
json_lines.append(json.loads(line))
|
||||
return rc, json_lines
|
||||
|
||||
return _run
|
||||
519
tests/fixtures/atcoder_abc100_tasks.html
vendored
Normal file
519
tests/fixtures/atcoder_abc100_tasks.html
vendored
Normal file
|
|
@ -0,0 +1,519 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tasks - AtCoder Beginner Contest 100</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="Content-Language" content="en" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta
|
||||
name="google-site-verification"
|
||||
content="nXGC_JxO0yoP1qBzMnYD_xgufO6leSLw1kyNo2HZltM"
|
||||
/>
|
||||
|
||||
<script
|
||||
async
|
||||
src="https://www.googletagmanager.com/gtag/js?id=G-RC512FD18N"
|
||||
></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || []
|
||||
function gtag() {
|
||||
dataLayer.push(arguments)
|
||||
}
|
||||
gtag('js', new Date())
|
||||
gtag('set', 'user_properties', {
|
||||
login_status: 'logged_out'
|
||||
})
|
||||
gtag('config', 'G-RC512FD18N')
|
||||
</script>
|
||||
|
||||
<meta
|
||||
name="description"
|
||||
content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online."
|
||||
/>
|
||||
<meta name="author" content="AtCoder Inc." />
|
||||
|
||||
<meta property="og:site_name" content="AtCoder" />
|
||||
|
||||
<meta property="og:title" content="Tasks - AtCoder Beginner Contest 100" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online."
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://atcoder.jp/contests/abc100/tasks"
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://img.atcoder.jp/assets/atcoder.png"
|
||||
/>
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@atcoder" />
|
||||
|
||||
<meta
|
||||
property="twitter:title"
|
||||
content="Tasks - AtCoder Beginner Contest 100"
|
||||
/>
|
||||
|
||||
<link
|
||||
href="//fonts.googleapis.com/css?family=Lato:400,700"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="//img.atcoder.jp/public/6372bb3/css/bootstrap.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="//img.atcoder.jp/public/6372bb3/css/base.css"
|
||||
/>
|
||||
<link
|
||||
rel="shortcut icon"
|
||||
type="image/png"
|
||||
href="//img.atcoder.jp/assets/favicon.png"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="//img.atcoder.jp/assets/atcoder.png" />
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/jquery-1.9.1.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/bootstrap.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/js.cookie.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment_js-ja.js"></script>
|
||||
<script>
|
||||
var LANG = 'en'
|
||||
var userScreenName = ''
|
||||
var csrfToken = 'q+4tZ4tLQh/4nobcpVAuiml6OVEZOdZDZURhPenxPbc='
|
||||
</script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/utils.js"></script>
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/contest.js"></script>
|
||||
<link
|
||||
href="//img.atcoder.jp/public/6372bb3/css/contest.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<script>
|
||||
var contestScreenName = 'abc100'
|
||||
var remainingText = 'Remaining Time'
|
||||
var countDownText = 'Contest begins in'
|
||||
var startTime = moment('2018-06-16T21:00:00+09:00')
|
||||
var endTime = moment('2018-06-16T22:40:00+09:00')
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/base.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
var __pParams = __pParams || []
|
||||
__pParams.push({
|
||||
client_id: '468',
|
||||
c_1: 'atcodercontest',
|
||||
c_2: 'ClientSite'
|
||||
})
|
||||
</script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="https://cdn.d2-apps.net/js/tr.js"
|
||||
async
|
||||
></script>
|
||||
|
||||
<div
|
||||
id="modal-contest-start"
|
||||
class="modal fade"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Contest started</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has begun.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-contest-end" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
aria-label="Close"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Contest is over</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has ended.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-div" class="float-container">
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button
|
||||
type="button"
|
||||
class="navbar-toggle collapsed"
|
||||
data-toggle="collapse"
|
||||
data-target="#navbar-collapse"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="icon-bar"></span><span class="icon-bar"></span
|
||||
><span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/home"></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a class="contest-title" href="/contests/abc100"
|
||||
>AtCoder Beginner Contest 100</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
href="#"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<img src="//img.atcoder.jp/assets/top/img/flag-lang/en.png" />
|
||||
English <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="/contests/abc100/tasks?lang=ja"
|
||||
><img
|
||||
src="//img.atcoder.jp/assets/top/img/flag-lang/ja.png"
|
||||
/>
|
||||
日本語</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/contests/abc100/tasks?lang=en"
|
||||
><img
|
||||
src="//img.atcoder.jp/assets/top/img/flag-lang/en.png"
|
||||
/>
|
||||
English</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
href="/register?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks"
|
||||
>Sign Up</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="/login?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks"
|
||||
>Sign In</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<form
|
||||
method="POST"
|
||||
name="form_logout"
|
||||
action="/logout?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="csrf_token"
|
||||
value="q+4tZ4tLQh/4nobcpVAuiml6OVEZOdZDZURhPenxPbc="
|
||||
/>
|
||||
</form>
|
||||
<div id="main-container" class="container" style="padding-top: 50px">
|
||||
<div class="row">
|
||||
<div id="contest-nav-tabs" class="col-sm-12 mb-2 cnvtb-fixed">
|
||||
<div>
|
||||
<small class="contest-duration">
|
||||
Contest Duration:
|
||||
<a
|
||||
href="http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2100&p1=248"
|
||||
target="blank"
|
||||
><time class="fixtime fixtime-full"
|
||||
>2018-06-16 21:00:00+0900</time
|
||||
></a
|
||||
>
|
||||
-
|
||||
<a
|
||||
href="http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2240&p1=248"
|
||||
target="blank"
|
||||
><time class="fixtime fixtime-full"
|
||||
>2018-06-16 22:40:00+0900</time
|
||||
></a
|
||||
>
|
||||
(local time) (100 minutes)
|
||||
</small>
|
||||
<small class="back-to-home pull-right"
|
||||
><a href="/home">Back to Home</a></small
|
||||
>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li>
|
||||
<a href="/contests/abc100"
|
||||
><span
|
||||
class="glyphicon glyphicon-home"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Top</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li class="active">
|
||||
<a href="/contests/abc100/tasks"
|
||||
><span
|
||||
class="glyphicon glyphicon-tasks"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Tasks</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/contests/abc100/clarifications"
|
||||
><span
|
||||
class="glyphicon glyphicon-question-sign"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Clarifications <span id="clar-badge" class="badge"></span
|
||||
></a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
class="dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
href="#"
|
||||
role="button"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
><span
|
||||
class="glyphicon glyphicon-list"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Results<span class="caret"></span
|
||||
></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a href="/contests/abc100/submissions"
|
||||
><span
|
||||
class="glyphicon glyphicon-globe"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
All Submissions</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/contests/abc100/standings"
|
||||
><span
|
||||
class="glyphicon glyphicon-sort-by-attributes-alt"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Standings</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/contests/abc100/standings/virtual"
|
||||
><span
|
||||
class="glyphicon glyphicon-sort-by-attributes-alt"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Virtual Standings</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/contests/abc100/editorial"
|
||||
><span
|
||||
class="glyphicon glyphicon-book"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
Editorial</a
|
||||
>
|
||||
</li>
|
||||
|
||||
<li class="pull-right">
|
||||
<a id="fix-cnvtb" href="javascript:void(0)"
|
||||
><span
|
||||
class="glyphicon glyphicon-pushpin"
|
||||
aria-hidden="true"
|
||||
></span
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<h2>Tasks</h2>
|
||||
<hr />
|
||||
|
||||
<div class="panel panel-default table-responsive">
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="3%" class="text-center"></th>
|
||||
<th>Task Name</th>
|
||||
<th width="10%" class="text-right no-break">Time Limit</th>
|
||||
<th width="10%" class="text-right no-break">
|
||||
Memory Limit
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center no-break">
|
||||
<a href="/contests/abc100/tasks/abc100_a">A</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/contests/abc100/tasks/abc100_a"
|
||||
>Happy Birthday!</a
|
||||
>
|
||||
</td>
|
||||
<td class="text-right">2 sec</td>
|
||||
<td class="text-right">976 MiB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-center no-break">
|
||||
<a href="/contests/abc100/tasks/abc100_b">B</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/contests/abc100/tasks/abc100_b"
|
||||
>Ringo's Favorite Numbers</a
|
||||
>
|
||||
</td>
|
||||
<td class="text-right">2 sec</td>
|
||||
<td class="text-right">976 MiB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-center no-break">
|
||||
<a href="/contests/abc100/tasks/abc100_c">C</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/contests/abc100/tasks/abc100_c">*3 or /2</a>
|
||||
</td>
|
||||
<td class="text-right">2 sec</td>
|
||||
<td class="text-right">976 MiB</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-center no-break">
|
||||
<a href="/contests/abc100/tasks/abc100_d">D</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/contests/abc100/tasks/abc100_d"
|
||||
>Patisserie ABC</a
|
||||
>
|
||||
</td>
|
||||
<td class="text-right">2 sec</td>
|
||||
<td class="text-right">976 MiB</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="btn-text-group">
|
||||
<a class="btn-text" href="/contests/abc100/tasks_print"
|
||||
>Tasks for printing</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div
|
||||
class="a2a_kit a2a_kit_size_20 a2a_default_style pull-right"
|
||||
data-a2a-url="https://atcoder.jp/contests/abc100/tasks?lang=en"
|
||||
data-a2a-title="Tasks - AtCoder Beginner Contest 100"
|
||||
>
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
|
||||
<a class="a2a_button_telegram"></a>
|
||||
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
</div>
|
||||
|
||||
<script async src="//static.addtoany.com/menu/page.js"></script>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 80px">
|
||||
<footer class="footer">
|
||||
<ul>
|
||||
<li><a href="/contests/abc100/rules">Rule</a></li>
|
||||
<li><a href="/contests/abc100/glossary">Glossary</a></li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/tos">Terms of service</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/personal">Information Protection Policy</a></li>
|
||||
<li><a href="/company">Company</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
<div class="text-center">
|
||||
<small id="copyright"
|
||||
>Copyright Since 2012 ©<a href="http://atcoder.co.jp"
|
||||
>AtCoder Inc.</a
|
||||
>
|
||||
All rights reserved.</small
|
||||
>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<p id="fixed-server-timer" class="contest-timer"></p>
|
||||
<div id="scroll-page-top" style="display: none">
|
||||
<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> Page
|
||||
Top
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1902
tests/fixtures/atcoder_contests.html
vendored
Normal file
1902
tests/fixtures/atcoder_contests.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
602
tests/fixtures/atcoder_task_abc100_a.html
vendored
Normal file
602
tests/fixtures/atcoder_task_abc100_a.html
vendored
Normal file
|
|
@ -0,0 +1,602 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>A - Happy Birthday!</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="google-site-verification" content="nXGC_JxO0yoP1qBzMnYD_xgufO6leSLw1kyNo2HZltM" />
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RC512FD18N"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('set', 'user_properties', {
|
||||
|
||||
'login_status': 'logged_out',
|
||||
|
||||
});
|
||||
gtag('config', 'G-RC512FD18N');
|
||||
</script>
|
||||
|
||||
|
||||
<meta name="description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.">
|
||||
<meta name="author" content="AtCoder Inc.">
|
||||
|
||||
<meta property="og:site_name" content="AtCoder">
|
||||
|
||||
<meta property="og:title" content="A - Happy Birthday!" />
|
||||
<meta property="og:description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://atcoder.jp/contests/abc100/tasks/abc100_a" />
|
||||
<meta property="og:image" content="https://img.atcoder.jp/assets/atcoder.png" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@atcoder" />
|
||||
|
||||
<meta property="twitter:title" content="A - Happy Birthday!" />
|
||||
|
||||
<link href="//fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/base.css">
|
||||
<link rel="shortcut icon" type="image/png" href="//img.atcoder.jp/assets/favicon.png">
|
||||
<link rel="apple-touch-icon" href="//img.atcoder.jp/assets/atcoder.png">
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/jquery-1.9.1.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/bootstrap.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/js.cookie.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment_js-ja.js"></script>
|
||||
<script>
|
||||
var LANG = "en";
|
||||
var userScreenName = "";
|
||||
var csrfToken = "RRHWPnDZqM+tdZpgbKRjH5FxiX5spw9S3/HKRbnyqok="
|
||||
</script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/utils.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/contest.js"></script>
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/contest.css" rel="stylesheet" />
|
||||
<script>
|
||||
var contestScreenName = "abc100";
|
||||
var remainingText = "Remaining Time";
|
||||
var countDownText = "Contest begins in";
|
||||
var startTime = moment("2018-06-16T21:00:00+09:00");
|
||||
var endTime = moment("2018-06-16T22:40:00+09:00");
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2.min.css" rel="stylesheet" />
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2-bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/select2.min.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ace.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ext-language_tools.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/run_prettify.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="//img.atcoder.jp/public/6372bb3/css/cdn/katex.min.css">
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/katex.min.js"></script>
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/auto-render.min.js"></script>
|
||||
<script>$(function(){$('var').each(function(){var html=$(this).html().replace(/<sub>/g,'_{').replace(/<\/sub>/g,'}');$(this).html('\\('+html+'\\)');});});</script>
|
||||
<script>
|
||||
var katexOptions = {
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true}
|
||||
],
|
||||
ignoredTags: ["script", "noscript", "style", "textarea", "code", "option"],
|
||||
ignoredClasses: ["prettyprint", "source-code-for-copy"],
|
||||
throwOnError: false
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", function() { renderMathInElement(document.body, katexOptions);});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/base.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var __pParams = __pParams || [];
|
||||
__pParams.push({client_id: '468', c_1: 'atcodercontest', c_2: 'ClientSite'});
|
||||
</script>
|
||||
<script type="text/javascript" src="https://cdn.d2-apps.net/js/tr.js" async></script>
|
||||
|
||||
|
||||
<div id="modal-contest-start" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest started</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has begun.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-contest-end" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest is over</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has ended.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-div" class="float-container">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
|
||||
<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/home"></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li><a class="contest-title" href="/contests/abc100">AtCoder Beginner Contest 100</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
<img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/tasks/abc100_a?lang=ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'> 日本語</a></li>
|
||||
<li><a href="/contests/abc100/tasks/abc100_a?lang=en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><a href="/register?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_a">Sign Up</a></li>
|
||||
<li><a href="/login?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_a">Sign In</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<form method="POST" name="form_logout" action="/logout?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_a">
|
||||
<input type="hidden" name="csrf_token" value="RRHWPnDZqM+tdZpgbKRjH5FxiX5spw9S3/HKRbnyqok=" />
|
||||
</form>
|
||||
<div id="main-container" class="container"
|
||||
style="padding-top:50px;">
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div id="contest-nav-tabs" class="col-sm-12 mb-2 cnvtb-fixed">
|
||||
<div>
|
||||
<small class="contest-duration">
|
||||
|
||||
Contest Duration:
|
||||
<a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2100&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 21:00:00+0900</time></a> - <a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2240&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 22:40:00+0900</time></a> (local time)
|
||||
(100 minutes)
|
||||
|
||||
</small>
|
||||
<small class="back-to-home pull-right"><a href="/home">Back to Home</a></small>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/contests/abc100"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Top</a></li>
|
||||
|
||||
<li class="active"><a href="/contests/abc100/tasks"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Tasks</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/clarifications"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> Clarifications <span id="clar-badge" class="badge" ></span></a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> Results<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/submissions"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> All Submissions</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Standings</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings/virtual"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Virtual Standings</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/editorial"><span class="glyphicon glyphicon-book" aria-hidden="true"></span> Editorial</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="pull-right"><a id="fix-cnvtb" href="javascript:void(0)"><span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<span class="h2">
|
||||
A - Happy Birthday!
|
||||
<a class="btn btn-default btn-sm" href="/contests/abc100/tasks/abc100_a/editorial">Editorial</a>
|
||||
</span>
|
||||
<span id="task-lang-btn" class="pull-right"><span data-lang="ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'></span> / <span data-lang="en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'></span></span>
|
||||
<script>
|
||||
$(function() {
|
||||
var ts = $('#task-statement span.lang');
|
||||
if (ts.children('span').size() <= 1) {
|
||||
$('#task-lang-btn').hide();
|
||||
ts.children('span').show();
|
||||
return;
|
||||
}
|
||||
|
||||
var REMEMBER_LB = 5;
|
||||
var LS_KEY = 'task_lang';
|
||||
var taskLang = getLS(LS_KEY) || '';
|
||||
function isTaskLangSet(taskLang) { return taskLang === 'ja' || taskLang === 'en';}
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('lang')) {
|
||||
setLS(LS_KEY, REMEMBER_LB);
|
||||
taskLang = LANG;
|
||||
}
|
||||
} else {
|
||||
taskLang = LANG;
|
||||
}
|
||||
ts.children('span.lang-' + taskLang).show();
|
||||
|
||||
$('#task-lang-btn span').click(function() {
|
||||
var l = $(this).data('lang');
|
||||
ts.children('span').hide();
|
||||
ts.children('span.lang-' + l).show();
|
||||
|
||||
taskLang = getLS(LS_KEY) || '';
|
||||
let changeTimes = 0;
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
changeTimes = REMEMBER_LB;
|
||||
} else {
|
||||
changeTimes = parseInt(taskLang, 10);
|
||||
if (isNaN(changeTimes)) changeTimes = 0;
|
||||
changeTimes++;
|
||||
}
|
||||
if (changeTimes < REMEMBER_LB) setLS(LS_KEY, changeTimes);
|
||||
else setLS(LS_KEY, l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<hr/>
|
||||
<p>
|
||||
Time Limit: 2 sec / Memory Limit: 976 MiB
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<div id="task-statement">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="lang">
|
||||
<span class="lang-ja">
|
||||
<p>配点: <var>100</var> 点 </p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>問題文</h3>
|
||||
<p>もうすぐ E869120 君と square1001 君の <var>16</var> 才の誕生日が来る.<br />
|
||||
そこで, AtCoder 王国の高橋君は, 円形のケーキ <var>1</var> 個に放射状に切れ目を入れ <var>16</var> 等分したものを, 彼らにプレゼントした. </p>
|
||||
<p>E869120 君はそのうち <var>A</var> 切れ、square1001 君は <var>B</var> 切れを食べようとした.<br />
|
||||
しかし, ケーキと一緒についていた紙を見ると, 「同じ人が隣り合う <var>2</var> 切れのケーキを両方取ってはならない」と書かれていた. </p>
|
||||
<p>さて、彼らは紙に書かれたことを守って、<var>2</var> 人とも食べたい数のケーキを取ることができるだろうか? </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>制約</h3>
|
||||
<ul>
|
||||
<li><var>A, B</var> は <var>1</var> 以上 <var>16</var> 以下の整数</li>
|
||||
<li><var>A+B</var> は <var>16</var> 以下である.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力</h3>
|
||||
<p>入力は以下の形式で標準入力から与えられる. </p>
|
||||
<pre><var>A</var> <var>B</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力</h3>
|
||||
<p>紙に書かれたことを守って, E869120 君と square1001 君両方が, 食べたい数のケーキを取ることができるならば <code>Yay!</code>, そうでなければ <code>:(</code> と出力しなさい.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 1</h3><pre>5 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 1</h3><pre>Yay!
|
||||
</pre>
|
||||
|
||||
<p>下の図のようにケーキを取れば、<var>2</var> 人とも目標を達成することができる.<br />
|
||||
<img alt=" " src="https://img.atcoder.jp/abc100/e87fa456a900ac9ae36671ae8bd5eeea.png" /></p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 2</h3><pre>8 8
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 2</h3><pre>Yay!
|
||||
</pre>
|
||||
|
||||
<p>下の図のようにケーキを取れば、<var>2</var> 人とも目標を達成することができる.<br />
|
||||
<img alt=" " src="https://img.atcoder.jp/abc100/a7989ac033e6ba86e14078864c20d9c5.png" /></p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 3</h3><pre>11 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 3</h3><pre>:(
|
||||
</pre>
|
||||
|
||||
<p>この場合, 残念ながら目標を達成する方法は <var>1</var> つもない. </p></section>
|
||||
</div>
|
||||
</span>
|
||||
<span class="lang-en">
|
||||
<p>Score: <var>100</var> points</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Problem Statement</h3>
|
||||
<p>E869120's and square1001's <var>16</var>-th birthday is coming soon.<br />
|
||||
Takahashi from AtCoder Kingdom gave them a round cake cut into <var>16</var> equal fan-shaped pieces.</p>
|
||||
<p>E869120 and square1001 were just about to eat <var>A</var> and <var>B</var> of those pieces, respectively,<br />
|
||||
when they found a note attached to the cake saying that "the same person should not take two adjacent pieces of cake".</p>
|
||||
<p>Can both of them obey the instruction in the note and take desired numbers of pieces of cake?</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Constraints</h3>
|
||||
<ul>
|
||||
<li><var>A</var> and <var>B</var> are integers between <var>1</var> and <var>16</var> (inclusive).</li>
|
||||
<li><var>A+B</var> is at most <var>16</var>.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Input</h3>
|
||||
<p>Input is given from Standard Input in the following format:</p>
|
||||
<pre><var>A</var> <var>B</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Output</h3>
|
||||
<p>If both E869120 and square1001 can obey the instruction in the note and take desired numbers of pieces of cake, print <code>Yay!</code>; otherwise, print <code>:(</code>.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 1</h3><pre>5 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 1</h3><pre>Yay!
|
||||
</pre>
|
||||
|
||||
<p>Both of them can take desired number of pieces as follows:
|
||||
<img alt=" " src="https://img.atcoder.jp/abc100/e87fa456a900ac9ae36671ae8bd5eeea.png" /></p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 2</h3><pre>8 8
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 2</h3><pre>Yay!
|
||||
</pre>
|
||||
|
||||
<p>Both of them can take desired number of pieces as follows:
|
||||
<img alt=" " src="https://img.atcoder.jp/abc100/a7989ac033e6ba86e14078864c20d9c5.png" /></p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 3</h3><pre>11 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 3</h3><pre>:(
|
||||
</pre>
|
||||
|
||||
<p>In this case, there is no way for them to take desired number of pieces, unfortunately.</p></section>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<div class="a2a_kit a2a_kit_size_20 a2a_default_style pull-right" data-a2a-url="https://atcoder.jp/contests/abc100/tasks/abc100_a?lang=en" data-a2a-title="A - Happy Birthday!">
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
|
||||
<a class="a2a_button_telegram"></a>
|
||||
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
</div>
|
||||
|
||||
|
||||
<script async src="//static.addtoany.com/menu/page.js"></script>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 80px;">
|
||||
<footer class="footer">
|
||||
|
||||
<ul>
|
||||
<li><a href="/contests/abc100/rules">Rule</a></li>
|
||||
<li><a href="/contests/abc100/glossary">Glossary</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/tos">Terms of service</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/personal">Information Protection Policy</a></li>
|
||||
<li><a href="/company">Company</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
|
||||
</ul>
|
||||
<div class="text-center">
|
||||
<small id="copyright">Copyright Since 2012 ©<a href="http://atcoder.co.jp">AtCoder Inc.</a> All rights reserved.</small>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<p id="fixed-server-timer" class="contest-timer"></p>
|
||||
<div id="scroll-page-top" style="display:none;"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> Page Top</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
600
tests/fixtures/atcoder_task_abc100_b.html
vendored
Normal file
600
tests/fixtures/atcoder_task_abc100_b.html
vendored
Normal file
|
|
@ -0,0 +1,600 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>B - Ringo's Favorite Numbers</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="google-site-verification" content="nXGC_JxO0yoP1qBzMnYD_xgufO6leSLw1kyNo2HZltM" />
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RC512FD18N"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('set', 'user_properties', {
|
||||
|
||||
'login_status': 'logged_out',
|
||||
|
||||
});
|
||||
gtag('config', 'G-RC512FD18N');
|
||||
</script>
|
||||
|
||||
|
||||
<meta name="description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.">
|
||||
<meta name="author" content="AtCoder Inc.">
|
||||
|
||||
<meta property="og:site_name" content="AtCoder">
|
||||
|
||||
<meta property="og:title" content="B - Ringo's Favorite Numbers" />
|
||||
<meta property="og:description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://atcoder.jp/contests/abc100/tasks/abc100_b" />
|
||||
<meta property="og:image" content="https://img.atcoder.jp/assets/atcoder.png" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@atcoder" />
|
||||
|
||||
<meta property="twitter:title" content="B - Ringo's Favorite Numbers" />
|
||||
|
||||
<link href="//fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/base.css">
|
||||
<link rel="shortcut icon" type="image/png" href="//img.atcoder.jp/assets/favicon.png">
|
||||
<link rel="apple-touch-icon" href="//img.atcoder.jp/assets/atcoder.png">
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/jquery-1.9.1.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/bootstrap.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/js.cookie.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment_js-ja.js"></script>
|
||||
<script>
|
||||
var LANG = "en";
|
||||
var userScreenName = "";
|
||||
var csrfToken = "jcqZoHtgdlDPapU/uheo04+cw+2+EssGGNrF7tJr004="
|
||||
</script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/utils.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/contest.js"></script>
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/contest.css" rel="stylesheet" />
|
||||
<script>
|
||||
var contestScreenName = "abc100";
|
||||
var remainingText = "Remaining Time";
|
||||
var countDownText = "Contest begins in";
|
||||
var startTime = moment("2018-06-16T21:00:00+09:00");
|
||||
var endTime = moment("2018-06-16T22:40:00+09:00");
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2.min.css" rel="stylesheet" />
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2-bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/select2.min.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ace.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ext-language_tools.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/run_prettify.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="//img.atcoder.jp/public/6372bb3/css/cdn/katex.min.css">
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/katex.min.js"></script>
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/auto-render.min.js"></script>
|
||||
<script>$(function(){$('var').each(function(){var html=$(this).html().replace(/<sub>/g,'_{').replace(/<\/sub>/g,'}');$(this).html('\\('+html+'\\)');});});</script>
|
||||
<script>
|
||||
var katexOptions = {
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true}
|
||||
],
|
||||
ignoredTags: ["script", "noscript", "style", "textarea", "code", "option"],
|
||||
ignoredClasses: ["prettyprint", "source-code-for-copy"],
|
||||
throwOnError: false
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", function() { renderMathInElement(document.body, katexOptions);});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/base.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var __pParams = __pParams || [];
|
||||
__pParams.push({client_id: '468', c_1: 'atcodercontest', c_2: 'ClientSite'});
|
||||
</script>
|
||||
<script type="text/javascript" src="https://cdn.d2-apps.net/js/tr.js" async></script>
|
||||
|
||||
|
||||
<div id="modal-contest-start" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest started</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has begun.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-contest-end" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest is over</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has ended.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-div" class="float-container">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
|
||||
<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/home"></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li><a class="contest-title" href="/contests/abc100">AtCoder Beginner Contest 100</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
<img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/tasks/abc100_b?lang=ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'> 日本語</a></li>
|
||||
<li><a href="/contests/abc100/tasks/abc100_b?lang=en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><a href="/register?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_b">Sign Up</a></li>
|
||||
<li><a href="/login?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_b">Sign In</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<form method="POST" name="form_logout" action="/logout?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_b">
|
||||
<input type="hidden" name="csrf_token" value="jcqZoHtgdlDPapU/uheo04+cw+2+EssGGNrF7tJr004=" />
|
||||
</form>
|
||||
<div id="main-container" class="container"
|
||||
style="padding-top:50px;">
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div id="contest-nav-tabs" class="col-sm-12 mb-2 cnvtb-fixed">
|
||||
<div>
|
||||
<small class="contest-duration">
|
||||
|
||||
Contest Duration:
|
||||
<a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2100&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 21:00:00+0900</time></a> - <a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2240&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 22:40:00+0900</time></a> (local time)
|
||||
(100 minutes)
|
||||
|
||||
</small>
|
||||
<small class="back-to-home pull-right"><a href="/home">Back to Home</a></small>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/contests/abc100"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Top</a></li>
|
||||
|
||||
<li class="active"><a href="/contests/abc100/tasks"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Tasks</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/clarifications"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> Clarifications <span id="clar-badge" class="badge" ></span></a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> Results<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/submissions"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> All Submissions</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Standings</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings/virtual"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Virtual Standings</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/editorial"><span class="glyphicon glyphicon-book" aria-hidden="true"></span> Editorial</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="pull-right"><a id="fix-cnvtb" href="javascript:void(0)"><span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<span class="h2">
|
||||
B - Ringo's Favorite Numbers
|
||||
<a class="btn btn-default btn-sm" href="/contests/abc100/tasks/abc100_b/editorial">Editorial</a>
|
||||
</span>
|
||||
<span id="task-lang-btn" class="pull-right"><span data-lang="ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'></span> / <span data-lang="en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'></span></span>
|
||||
<script>
|
||||
$(function() {
|
||||
var ts = $('#task-statement span.lang');
|
||||
if (ts.children('span').size() <= 1) {
|
||||
$('#task-lang-btn').hide();
|
||||
ts.children('span').show();
|
||||
return;
|
||||
}
|
||||
|
||||
var REMEMBER_LB = 5;
|
||||
var LS_KEY = 'task_lang';
|
||||
var taskLang = getLS(LS_KEY) || '';
|
||||
function isTaskLangSet(taskLang) { return taskLang === 'ja' || taskLang === 'en';}
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('lang')) {
|
||||
setLS(LS_KEY, REMEMBER_LB);
|
||||
taskLang = LANG;
|
||||
}
|
||||
} else {
|
||||
taskLang = LANG;
|
||||
}
|
||||
ts.children('span.lang-' + taskLang).show();
|
||||
|
||||
$('#task-lang-btn span').click(function() {
|
||||
var l = $(this).data('lang');
|
||||
ts.children('span').hide();
|
||||
ts.children('span.lang-' + l).show();
|
||||
|
||||
taskLang = getLS(LS_KEY) || '';
|
||||
let changeTimes = 0;
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
changeTimes = REMEMBER_LB;
|
||||
} else {
|
||||
changeTimes = parseInt(taskLang, 10);
|
||||
if (isNaN(changeTimes)) changeTimes = 0;
|
||||
changeTimes++;
|
||||
}
|
||||
if (changeTimes < REMEMBER_LB) setLS(LS_KEY, changeTimes);
|
||||
else setLS(LS_KEY, l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<hr/>
|
||||
<p>
|
||||
Time Limit: 2 sec / Memory Limit: 976 MiB
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<div id="task-statement">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="lang">
|
||||
<span class="lang-ja">
|
||||
<p>配点: <var>200</var> 点</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>問題文</h3>
|
||||
<p>今日は, 記念すべき AtCoder Beginner Contest 100 が開催される. そのため, 高橋君はりんごさんに, ある整数をプレゼントしようと思った.<br />
|
||||
今日のコンテストは「AtCoder Beginner Contest 100」なので, りんごさんは <var>100</var> で <strong>ちょうど</strong> <var>D</var> 回割りきれる正の整数をプレゼントされると喜ぶ. </p>
|
||||
<p>さて, りんごさんがプレゼントされると喜ぶような整数のうち <var>N</var> 番目に小さいものを求めなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>制約</h3>
|
||||
<ul>
|
||||
<li><var>D</var> は <var>0, 1, 2</var> のいずれかである</li>
|
||||
<li><var>N</var> は <var>1</var> 以上 <var>100</var> 以下の整数</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力</h3>
|
||||
<p>入力は以下の形式で標準入力から与えられる. </p>
|
||||
<pre><var>D</var> <var>N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力</h3>
|
||||
<p><var>100</var> でちょうど <var>D</var> 回割りきれる正の整数の中で <var>N</var> 番目に小さいものを出力しなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 1</h3><pre>0 5
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 1</h3><pre>5
|
||||
</pre>
|
||||
|
||||
<p><var>100</var> でちょうど <var>0</var> 回割り切れる(すなわち, <var>100</var> で割り切れない)整数は, <var>1</var>, <var>2</var>, <var>3</var>, <var>4</var>, <var>5</var>, <var>6</var>, <var>7</var>, ... と続く.<br />
|
||||
よって, <var>5</var> 番目に小さいりんごさんが喜ぶ整数は <var>5</var> である. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 2</h3><pre>1 11
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 2</h3><pre>1100
|
||||
</pre>
|
||||
|
||||
<p><var>100</var> でちょうど <var>1</var> 回割り切れる整数は, <var>100</var>, <var>200</var>, <var>300</var>, <var>400</var>, <var>500</var>, <var>600</var>, <var>700</var>, <var>800</var>, <var>900</var>, <var>1 \ 000</var>, <var>1 \ 100</var>, ... と続く.<br />
|
||||
よって, 求めたい整数は <var>1 \ 100</var> である. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 3</h3><pre>2 85
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 3</h3><pre>850000
|
||||
</pre>
|
||||
|
||||
<p><var>100</var> でちょうど <var>2</var> 回割り切れる整数は, <var>10 \ 000</var>, <var>20 \ 000</var>, <var>30 \ 000</var>, ... と続く.<br />
|
||||
よって, 求めたい整数は <var>850 \ 000</var> である. </p></section>
|
||||
</div>
|
||||
</span>
|
||||
<span class="lang-en">
|
||||
<p>Score: <var>200</var> points</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Problem Statement</h3>
|
||||
<p>Today, the memorable AtCoder Beginner Contest 100 takes place. On this occasion, Takahashi would like to give an integer to Ringo.<br />
|
||||
As the name of the contest is AtCoder Beginner Contest 100, Ringo would be happy if he is given a positive integer that can be divided by <var>100</var> <strong>exactly</strong> <var>D</var> times.</p>
|
||||
<p>Find the <var>N</var>-th smallest integer that would make Ringo happy.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Constraints</h3>
|
||||
<ul>
|
||||
<li><var>D</var> is <var>0</var>, <var>1</var> or <var>2</var>.</li>
|
||||
<li><var>N</var> is an integer between <var>1</var> and <var>100</var> (inclusive).</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Input</h3>
|
||||
<p>Input is given from Standard Input in the following format:</p>
|
||||
<pre><var>D</var> <var>N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Output</h3>
|
||||
<p>Print the <var>N</var>-th smallest integer that can be divided by <var>100</var> exactly <var>D</var> times.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 1</h3><pre>0 5
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 1</h3><pre>5
|
||||
</pre>
|
||||
|
||||
<p>The integers that can be divided by <var>100</var> exactly <var>0</var> times (that is, not divisible by <var>100</var>) are as follows: <var>1</var>, <var>2</var>, <var>3</var>, <var>4</var>, <var>5</var>, <var>6</var>, <var>7</var>, ...<br />
|
||||
Thus, the <var>5</var>-th smallest integer that would make Ringo happy is <var>5</var>. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 2</h3><pre>1 11
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 2</h3><pre>1100
|
||||
</pre>
|
||||
|
||||
<p>The integers that can be divided by <var>100</var> exactly once are as follows: <var>100</var>, <var>200</var>, <var>300</var>, <var>400</var>, <var>500</var>, <var>600</var>, <var>700</var>, <var>800</var>, <var>900</var>, <var>1 \ 000</var>, <var>1 \ 100</var>, ...<br />
|
||||
Thus, the integer we are seeking is <var>1 \ 100</var>.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 3</h3><pre>2 85
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 3</h3><pre>850000
|
||||
</pre>
|
||||
|
||||
<p>The integers that can be divided by <var>100</var> exactly twice are as follows: <var>10 \ 000</var>, <var>20 \ 000</var>, <var>30 \ 000</var>, ...<br />
|
||||
Thus, the integer we are seeking is <var>850 \ 000</var>.</p></section>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<div class="a2a_kit a2a_kit_size_20 a2a_default_style pull-right" data-a2a-url="https://atcoder.jp/contests/abc100/tasks/abc100_b?lang=en" data-a2a-title="B - Ringo's Favorite Numbers">
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
|
||||
<a class="a2a_button_telegram"></a>
|
||||
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
</div>
|
||||
|
||||
|
||||
<script async src="//static.addtoany.com/menu/page.js"></script>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 80px;">
|
||||
<footer class="footer">
|
||||
|
||||
<ul>
|
||||
<li><a href="/contests/abc100/rules">Rule</a></li>
|
||||
<li><a href="/contests/abc100/glossary">Glossary</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/tos">Terms of service</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/personal">Information Protection Policy</a></li>
|
||||
<li><a href="/company">Company</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
|
||||
</ul>
|
||||
<div class="text-center">
|
||||
<small id="copyright">Copyright Since 2012 ©<a href="http://atcoder.co.jp">AtCoder Inc.</a> All rights reserved.</small>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<p id="fixed-server-timer" class="contest-timer"></p>
|
||||
<div id="scroll-page-top" style="display:none;"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> Page Top</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
618
tests/fixtures/atcoder_task_abc100_c.html
vendored
Normal file
618
tests/fixtures/atcoder_task_abc100_c.html
vendored
Normal file
|
|
@ -0,0 +1,618 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>C - *3 or /2</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="google-site-verification" content="nXGC_JxO0yoP1qBzMnYD_xgufO6leSLw1kyNo2HZltM" />
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RC512FD18N"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('set', 'user_properties', {
|
||||
|
||||
'login_status': 'logged_out',
|
||||
|
||||
});
|
||||
gtag('config', 'G-RC512FD18N');
|
||||
</script>
|
||||
|
||||
|
||||
<meta name="description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.">
|
||||
<meta name="author" content="AtCoder Inc.">
|
||||
|
||||
<meta property="og:site_name" content="AtCoder">
|
||||
|
||||
<meta property="og:title" content="C - *3 or /2" />
|
||||
<meta property="og:description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://atcoder.jp/contests/abc100/tasks/abc100_c" />
|
||||
<meta property="og:image" content="https://img.atcoder.jp/assets/atcoder.png" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@atcoder" />
|
||||
|
||||
<meta property="twitter:title" content="C - *3 or /2" />
|
||||
|
||||
<link href="//fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/base.css">
|
||||
<link rel="shortcut icon" type="image/png" href="//img.atcoder.jp/assets/favicon.png">
|
||||
<link rel="apple-touch-icon" href="//img.atcoder.jp/assets/atcoder.png">
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/jquery-1.9.1.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/bootstrap.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/js.cookie.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment_js-ja.js"></script>
|
||||
<script>
|
||||
var LANG = "en";
|
||||
var userScreenName = "";
|
||||
var csrfToken = "KwoiS7wTPLvccvgUDoQZ6H++fkjXMCchJrW6/YFqOJM="
|
||||
</script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/utils.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/contest.js"></script>
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/contest.css" rel="stylesheet" />
|
||||
<script>
|
||||
var contestScreenName = "abc100";
|
||||
var remainingText = "Remaining Time";
|
||||
var countDownText = "Contest begins in";
|
||||
var startTime = moment("2018-06-16T21:00:00+09:00");
|
||||
var endTime = moment("2018-06-16T22:40:00+09:00");
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2.min.css" rel="stylesheet" />
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2-bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/select2.min.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ace.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ext-language_tools.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/run_prettify.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="//img.atcoder.jp/public/6372bb3/css/cdn/katex.min.css">
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/katex.min.js"></script>
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/auto-render.min.js"></script>
|
||||
<script>$(function(){$('var').each(function(){var html=$(this).html().replace(/<sub>/g,'_{').replace(/<\/sub>/g,'}');$(this).html('\\('+html+'\\)');});});</script>
|
||||
<script>
|
||||
var katexOptions = {
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true}
|
||||
],
|
||||
ignoredTags: ["script", "noscript", "style", "textarea", "code", "option"],
|
||||
ignoredClasses: ["prettyprint", "source-code-for-copy"],
|
||||
throwOnError: false
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", function() { renderMathInElement(document.body, katexOptions);});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/base.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var __pParams = __pParams || [];
|
||||
__pParams.push({client_id: '468', c_1: 'atcodercontest', c_2: 'ClientSite'});
|
||||
</script>
|
||||
<script type="text/javascript" src="https://cdn.d2-apps.net/js/tr.js" async></script>
|
||||
|
||||
|
||||
<div id="modal-contest-start" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest started</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has begun.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-contest-end" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest is over</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has ended.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-div" class="float-container">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
|
||||
<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/home"></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li><a class="contest-title" href="/contests/abc100">AtCoder Beginner Contest 100</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
<img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/tasks/abc100_c?lang=ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'> 日本語</a></li>
|
||||
<li><a href="/contests/abc100/tasks/abc100_c?lang=en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><a href="/register?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_c">Sign Up</a></li>
|
||||
<li><a href="/login?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_c">Sign In</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<form method="POST" name="form_logout" action="/logout?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_c">
|
||||
<input type="hidden" name="csrf_token" value="KwoiS7wTPLvccvgUDoQZ6H++fkjXMCchJrW6/YFqOJM=" />
|
||||
</form>
|
||||
<div id="main-container" class="container"
|
||||
style="padding-top:50px;">
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div id="contest-nav-tabs" class="col-sm-12 mb-2 cnvtb-fixed">
|
||||
<div>
|
||||
<small class="contest-duration">
|
||||
|
||||
Contest Duration:
|
||||
<a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2100&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 21:00:00+0900</time></a> - <a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2240&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 22:40:00+0900</time></a> (local time)
|
||||
(100 minutes)
|
||||
|
||||
</small>
|
||||
<small class="back-to-home pull-right"><a href="/home">Back to Home</a></small>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/contests/abc100"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Top</a></li>
|
||||
|
||||
<li class="active"><a href="/contests/abc100/tasks"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Tasks</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/clarifications"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> Clarifications <span id="clar-badge" class="badge" ></span></a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> Results<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/submissions"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> All Submissions</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Standings</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings/virtual"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Virtual Standings</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/editorial"><span class="glyphicon glyphicon-book" aria-hidden="true"></span> Editorial</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="pull-right"><a id="fix-cnvtb" href="javascript:void(0)"><span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<span class="h2">
|
||||
C - *3 or /2
|
||||
<a class="btn btn-default btn-sm" href="/contests/abc100/tasks/abc100_c/editorial">Editorial</a>
|
||||
</span>
|
||||
<span id="task-lang-btn" class="pull-right"><span data-lang="ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'></span> / <span data-lang="en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'></span></span>
|
||||
<script>
|
||||
$(function() {
|
||||
var ts = $('#task-statement span.lang');
|
||||
if (ts.children('span').size() <= 1) {
|
||||
$('#task-lang-btn').hide();
|
||||
ts.children('span').show();
|
||||
return;
|
||||
}
|
||||
|
||||
var REMEMBER_LB = 5;
|
||||
var LS_KEY = 'task_lang';
|
||||
var taskLang = getLS(LS_KEY) || '';
|
||||
function isTaskLangSet(taskLang) { return taskLang === 'ja' || taskLang === 'en';}
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('lang')) {
|
||||
setLS(LS_KEY, REMEMBER_LB);
|
||||
taskLang = LANG;
|
||||
}
|
||||
} else {
|
||||
taskLang = LANG;
|
||||
}
|
||||
ts.children('span.lang-' + taskLang).show();
|
||||
|
||||
$('#task-lang-btn span').click(function() {
|
||||
var l = $(this).data('lang');
|
||||
ts.children('span').hide();
|
||||
ts.children('span.lang-' + l).show();
|
||||
|
||||
taskLang = getLS(LS_KEY) || '';
|
||||
let changeTimes = 0;
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
changeTimes = REMEMBER_LB;
|
||||
} else {
|
||||
changeTimes = parseInt(taskLang, 10);
|
||||
if (isNaN(changeTimes)) changeTimes = 0;
|
||||
changeTimes++;
|
||||
}
|
||||
if (changeTimes < REMEMBER_LB) setLS(LS_KEY, changeTimes);
|
||||
else setLS(LS_KEY, l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<hr/>
|
||||
<p>
|
||||
Time Limit: 2 sec / Memory Limit: 976 MiB
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<div id="task-statement">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="lang">
|
||||
<span class="lang-ja">
|
||||
<p>配点: <var>300</var> 点</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>問題文</h3>
|
||||
<p>AtCoder Beginner Contest 100 の開催にともなって, AtCoder 社では長さ <var>N</var> の数列 <var>a = </var>{<var>a_1, a_2, a_3, ..., a_N</var>} が飾られることになった. <br />
|
||||
社員のすぬけ君は, この数列で遊んでみようと思った. </p>
|
||||
<p>具体的には, 以下の操作をできるだけ多くの回数繰り返そうと思った. </p>
|
||||
<pre><var>1 \leq i \leq N</var> を満たす全ての <var>i</var> に対して, それぞれ「<var>a_i</var> の値を <var>2</var> で割る」「<var>a_i</var> の値を <var>3</var> 倍する」のどちらかを行う.
|
||||
ただし, 全ての <var>i</var> に対して <var>3</var> 倍することはできず, 操作後の <var>a_i</var> の値は整数でなければならない.
|
||||
</pre>
|
||||
|
||||
<p>最大で何回の操作が可能か, 求めなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>制約</h3>
|
||||
<ul>
|
||||
<li><var>N</var> は <var>1</var> 以上 <var>10 \ 000</var> 以下の整数</li>
|
||||
<li><var>a_i</var> は <var>1</var> 以上 <var>1 \ 000 \ 000 \ 000</var> 以下の整数</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力</h3>
|
||||
<p>入力は以下の形式で標準入力から与えられる. </p>
|
||||
<pre><var>N</var>
|
||||
<var>a_1</var> <var>a_2</var> <var>a_3</var> <var>...</var> <var>a_N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力</h3>
|
||||
<p>すぬけ君が行える最大の操作回数を出力しなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 1</h3><pre>3
|
||||
5 2 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 1</h3><pre>3
|
||||
</pre>
|
||||
|
||||
<p>最初, 数列は <var>{5, 2, 4}</var> であるが, 以下のように操作すれば <var>3</var> 回の操作を行うことができる. </p>
|
||||
<ul>
|
||||
<li>最初に, <var>a_1</var> を <var>3</var> 倍し, <var>a_2</var> を <var>3</var> 倍し, <var>a_3</var> を <var>2</var> で割る. すると数列は <var>{15, 6, 2}</var> となる.</li>
|
||||
<li>次に, <var>a_1</var> を <var>3</var> 倍し, <var>a_2</var> を <var>2</var> で割り, <var>a_3</var> を <var>3</var> 倍する. すると数列は <var>{45, 3, 6}</var> となる.</li>
|
||||
<li>最後に, <var>a_1</var> を <var>3</var> 倍し, <var>a_2</var> を <var>3</var> 倍し, <var>a_3</var> を <var>2</var> で割る. すると数列は <var>{135, 9, 3}</var> となる.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 2</h3><pre>4
|
||||
631 577 243 199
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 2</h3><pre>0
|
||||
</pre>
|
||||
|
||||
<p>全ての要素が奇数なので, 操作はできない. よって答えは <var>0</var> である. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 3</h3><pre>10
|
||||
2184 2126 1721 1800 1024 2528 3360 1945 1280 1776
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 3</h3><pre>39
|
||||
</pre></section>
|
||||
</div>
|
||||
</span>
|
||||
<span class="lang-en">
|
||||
<p>Score: <var>300</var> points</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Problem Statement</h3>
|
||||
<p>As AtCoder Beginner Contest 100 is taking place, the office of AtCoder, Inc. is decorated with a sequence of length <var>N</var>, <var>a = </var>{<var>a_1, a_2, a_3, ..., a_N</var>}.<br />
|
||||
Snuke, an employee, would like to play with this sequence.</p>
|
||||
<p>Specifically, he would like to repeat the following operation as many times as possible:</p>
|
||||
<pre>For every <var>i</var> satisfying <var>1 \leq i \leq N</var>, perform one of the following: "divide <var>a_i</var> by <var>2</var>" and "multiply <var>a_i</var> by <var>3</var>".
|
||||
Here, choosing "multiply <var>a_i</var> by <var>3</var>" for every <var>i</var> is not allowed, and the value of <var>a_i</var> after the operation must be an integer.
|
||||
</pre>
|
||||
|
||||
<p>At most how many operations can be performed?</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Constraints</h3>
|
||||
<ul>
|
||||
<li><var>N</var> is an integer between <var>1</var> and <var>10 \ 000</var> (inclusive).</li>
|
||||
<li><var>a_i</var> is an integer between <var>1</var> and <var>1 \ 000 \ 000 \ 000</var> (inclusive).</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Input</h3>
|
||||
<p>Input is given from Standard Input in the following format:</p>
|
||||
<pre><var>N</var>
|
||||
<var>a_1</var> <var>a_2</var> <var>a_3</var> <var>...</var> <var>a_N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Output</h3>
|
||||
<p>Print the maximum number of operations that Snuke can perform.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 1</h3><pre>3
|
||||
5 2 4
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 1</h3><pre>3
|
||||
</pre>
|
||||
|
||||
<p>The sequence is initially <var>{5, 2, 4}</var>. Three operations can be performed as follows:</p>
|
||||
<ul>
|
||||
<li>First, multiply <var>a_1</var> by <var>3</var>, multiply <var>a_2</var> by <var>3</var> and divide <var>a_3</var> by <var>2</var>. The sequence is now <var>{15, 6, 2}</var>.</li>
|
||||
<li>Next, multiply <var>a_1</var> by <var>3</var>, divide <var>a_2</var> by <var>2</var> and multiply <var>a_3</var> by <var>3</var>. The sequence is now <var>{45, 3, 6}</var>.</li>
|
||||
<li>Finally, multiply <var>a_1</var> by <var>3</var>, multiply <var>a_2</var> by <var>3</var> and divide <var>a_3</var> by <var>2</var>. The sequence is now <var>{135, 9, 3}</var>.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 2</h3><pre>4
|
||||
631 577 243 199
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 2</h3><pre>0
|
||||
</pre>
|
||||
|
||||
<p>No operation can be performed since all the elements are odd. Thus, the answer is <var>0</var>.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 3</h3><pre>10
|
||||
2184 2126 1721 1800 1024 2528 3360 1945 1280 1776
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 3</h3><pre>39
|
||||
</pre></section>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<div class="a2a_kit a2a_kit_size_20 a2a_default_style pull-right" data-a2a-url="https://atcoder.jp/contests/abc100/tasks/abc100_c?lang=en" data-a2a-title="C - *3 or /2">
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
|
||||
<a class="a2a_button_telegram"></a>
|
||||
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
</div>
|
||||
|
||||
|
||||
<script async src="//static.addtoany.com/menu/page.js"></script>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 80px;">
|
||||
<footer class="footer">
|
||||
|
||||
<ul>
|
||||
<li><a href="/contests/abc100/rules">Rule</a></li>
|
||||
<li><a href="/contests/abc100/glossary">Glossary</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/tos">Terms of service</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/personal">Information Protection Policy</a></li>
|
||||
<li><a href="/company">Company</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
|
||||
</ul>
|
||||
<div class="text-center">
|
||||
<small id="copyright">Copyright Since 2012 ©<a href="http://atcoder.co.jp">AtCoder Inc.</a> All rights reserved.</small>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<p id="fixed-server-timer" class="contest-timer"></p>
|
||||
<div id="scroll-page-top" style="display:none;"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> Page Top</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
728
tests/fixtures/atcoder_task_abc100_d.html
vendored
Normal file
728
tests/fixtures/atcoder_task_abc100_d.html
vendored
Normal file
|
|
@ -0,0 +1,728 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>D - Patisserie ABC</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="google-site-verification" content="nXGC_JxO0yoP1qBzMnYD_xgufO6leSLw1kyNo2HZltM" />
|
||||
|
||||
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-RC512FD18N"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('set', 'user_properties', {
|
||||
|
||||
'login_status': 'logged_out',
|
||||
|
||||
});
|
||||
gtag('config', 'G-RC512FD18N');
|
||||
</script>
|
||||
|
||||
|
||||
<meta name="description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.">
|
||||
<meta name="author" content="AtCoder Inc.">
|
||||
|
||||
<meta property="og:site_name" content="AtCoder">
|
||||
|
||||
<meta property="og:title" content="D - Patisserie ABC" />
|
||||
<meta property="og:description" content="AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://atcoder.jp/contests/abc100/tasks/abc100_d" />
|
||||
<meta property="og:image" content="https://img.atcoder.jp/assets/atcoder.png" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@atcoder" />
|
||||
|
||||
<meta property="twitter:title" content="D - Patisserie ABC" />
|
||||
|
||||
<link href="//fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="//img.atcoder.jp/public/6372bb3/css/base.css">
|
||||
<link rel="shortcut icon" type="image/png" href="//img.atcoder.jp/assets/favicon.png">
|
||||
<link rel="apple-touch-icon" href="//img.atcoder.jp/assets/atcoder.png">
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/jquery-1.9.1.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/bootstrap.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/js.cookie.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment.min.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/moment_js-ja.js"></script>
|
||||
<script>
|
||||
var LANG = "en";
|
||||
var userScreenName = "";
|
||||
var csrfToken = "GAGswbeHt5p1jIJSPp2R1sTxFC3jW6sLK2K7L2aRmUI="
|
||||
</script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/utils.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/contest.js"></script>
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/contest.css" rel="stylesheet" />
|
||||
<script>
|
||||
var contestScreenName = "abc100";
|
||||
var remainingText = "Remaining Time";
|
||||
var countDownText = "Contest begins in";
|
||||
var startTime = moment("2018-06-16T21:00:00+09:00");
|
||||
var endTime = moment("2018-06-16T22:40:00+09:00");
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2.min.css" rel="stylesheet" />
|
||||
<link href="//img.atcoder.jp/public/6372bb3/css/cdn/select2-bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/lib/select2.min.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ace.js"></script>
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/ace/ext-language_tools.js"></script>
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/cdn/run_prettify.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="//img.atcoder.jp/public/6372bb3/css/cdn/katex.min.css">
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/katex.min.js"></script>
|
||||
<script defer src="//img.atcoder.jp/public/6372bb3/js/cdn/auto-render.min.js"></script>
|
||||
<script>$(function(){$('var').each(function(){var html=$(this).html().replace(/<sub>/g,'_{').replace(/<\/sub>/g,'}');$(this).html('\\('+html+'\\)');});});</script>
|
||||
<script>
|
||||
var katexOptions = {
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true}
|
||||
],
|
||||
ignoredTags: ["script", "noscript", "style", "textarea", "code", "option"],
|
||||
ignoredClasses: ["prettyprint", "source-code-for-copy"],
|
||||
throwOnError: false
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", function() { renderMathInElement(document.body, katexOptions);});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script src="//img.atcoder.jp/public/6372bb3/js/base.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var __pParams = __pParams || [];
|
||||
__pParams.push({client_id: '468', c_1: 'atcodercontest', c_2: 'ClientSite'});
|
||||
</script>
|
||||
<script type="text/javascript" src="https://cdn.d2-apps.net/js/tr.js" async></script>
|
||||
|
||||
|
||||
<div id="modal-contest-start" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest started</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has begun.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-contest-end" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Contest is over</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>AtCoder Beginner Contest 100 has ended.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-div" class="float-container">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false">
|
||||
<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/home"></a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" id="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li><a class="contest-title" href="/contests/abc100">AtCoder Beginner Contest 100</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
<img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/tasks/abc100_d?lang=ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'> 日本語</a></li>
|
||||
<li><a href="/contests/abc100/tasks/abc100_d?lang=en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'> English</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><a href="/register?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_d">Sign Up</a></li>
|
||||
<li><a href="/login?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_d">Sign In</a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<form method="POST" name="form_logout" action="/logout?continue=https%3A%2F%2Fatcoder.jp%2Fcontests%2Fabc100%2Ftasks%2Fabc100_d">
|
||||
<input type="hidden" name="csrf_token" value="GAGswbeHt5p1jIJSPp2R1sTxFC3jW6sLK2K7L2aRmUI=" />
|
||||
</form>
|
||||
<div id="main-container" class="container"
|
||||
style="padding-top:50px;">
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div id="contest-nav-tabs" class="col-sm-12 mb-2 cnvtb-fixed">
|
||||
<div>
|
||||
<small class="contest-duration">
|
||||
|
||||
Contest Duration:
|
||||
<a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2100&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 21:00:00+0900</time></a> - <a href='http://www.timeanddate.com/worldclock/fixedtime.html?iso=20180616T2240&p1=248' target='blank'><time class='fixtime fixtime-full'>2018-06-16 22:40:00+0900</time></a> (local time)
|
||||
(100 minutes)
|
||||
|
||||
</small>
|
||||
<small class="back-to-home pull-right"><a href="/home">Back to Home</a></small>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="/contests/abc100"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Top</a></li>
|
||||
|
||||
<li class="active"><a href="/contests/abc100/tasks"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> Tasks</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/clarifications"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span> Clarifications <span id="clar-badge" class="badge" ></span></a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> Results<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/contests/abc100/submissions"><span class="glyphicon glyphicon-globe" aria-hidden="true"></span> All Submissions</a></li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Standings</a></li>
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/standings/virtual"><span class="glyphicon glyphicon-sort-by-attributes-alt" aria-hidden="true"></span> Virtual Standings</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li><a href="/contests/abc100/editorial"><span class="glyphicon glyphicon-book" aria-hidden="true"></span> Editorial</a></li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="pull-right"><a id="fix-cnvtb" href="javascript:void(0)"><span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<span class="h2">
|
||||
D - Patisserie ABC
|
||||
<a class="btn btn-default btn-sm" href="/contests/abc100/tasks/abc100_d/editorial">Editorial</a>
|
||||
</span>
|
||||
<span id="task-lang-btn" class="pull-right"><span data-lang="ja"><img src='//img.atcoder.jp/assets/top/img/flag-lang/ja.png'></span> / <span data-lang="en"><img src='//img.atcoder.jp/assets/top/img/flag-lang/en.png'></span></span>
|
||||
<script>
|
||||
$(function() {
|
||||
var ts = $('#task-statement span.lang');
|
||||
if (ts.children('span').size() <= 1) {
|
||||
$('#task-lang-btn').hide();
|
||||
ts.children('span').show();
|
||||
return;
|
||||
}
|
||||
|
||||
var REMEMBER_LB = 5;
|
||||
var LS_KEY = 'task_lang';
|
||||
var taskLang = getLS(LS_KEY) || '';
|
||||
function isTaskLangSet(taskLang) { return taskLang === 'ja' || taskLang === 'en';}
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('lang')) {
|
||||
setLS(LS_KEY, REMEMBER_LB);
|
||||
taskLang = LANG;
|
||||
}
|
||||
} else {
|
||||
taskLang = LANG;
|
||||
}
|
||||
ts.children('span.lang-' + taskLang).show();
|
||||
|
||||
$('#task-lang-btn span').click(function() {
|
||||
var l = $(this).data('lang');
|
||||
ts.children('span').hide();
|
||||
ts.children('span.lang-' + l).show();
|
||||
|
||||
taskLang = getLS(LS_KEY) || '';
|
||||
let changeTimes = 0;
|
||||
if (isTaskLangSet(taskLang)) {
|
||||
changeTimes = REMEMBER_LB;
|
||||
} else {
|
||||
changeTimes = parseInt(taskLang, 10);
|
||||
if (isNaN(changeTimes)) changeTimes = 0;
|
||||
changeTimes++;
|
||||
}
|
||||
if (changeTimes < REMEMBER_LB) setLS(LS_KEY, changeTimes);
|
||||
else setLS(LS_KEY, l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<hr/>
|
||||
<p>
|
||||
Time Limit: 2 sec / Memory Limit: 976 MiB
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
<div id="task-statement">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<span class="lang">
|
||||
<span class="lang-ja">
|
||||
<p>配点: <var>400</var> 点</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>問題文</h3>
|
||||
<p>高橋君はプロのパティシエになり, AtCoder Beginner Contest 100 を記念して, 「ABC洋菓子店」というお店を開いた. </p>
|
||||
<p>ABC洋菓子店では, <var>N</var> 種類のケーキを売っている.<br />
|
||||
各種類のケーキには「綺麗さ」「おいしさ」「人気度」の <var>3</var> つの値を持ち, <var>i</var> 種類目のケーキの綺麗さは <var>x_i</var>, おいしさは <var>y_i</var>, 人気度は <var>z_i</var> である.<br />
|
||||
これらの値は <var>0</var> 以下である可能性もある. </p>
|
||||
<p>りんごさんは, ABC洋菓子店で <var>M</var> 個のケーキを食べることにした. 彼は次のように, 食べるケーキの組み合わせを選ぶことにした. </p>
|
||||
<ul>
|
||||
<li>同じ種類のケーキを <var>2</var> 個以上食べない.</li>
|
||||
<li>上の条件を満たしつつ, (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) が最大になるように選ぶ.</li>
|
||||
</ul>
|
||||
<p>このとき, りんごさんが選ぶケーキの (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) の最大値を求めなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>制約</h3>
|
||||
<ul>
|
||||
<li><var>N</var> は <var>1</var> 以上 <var>1 \ 000</var> 以下の整数</li>
|
||||
<li><var>M</var> は <var>0</var> 以上 <var>N</var> 以下の整数</li>
|
||||
<li><var>x_i, y_i, z_i \ (1 \leq i \leq N)</var> は, それぞれ <var>-10 \ 000 \ 000 \ 000</var> 以上 <var>10 \ 000 \ 000 \ 000</var> 以下の整数.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力</h3>
|
||||
<p>入力は以下の形式で標準入力から与えられる. </p>
|
||||
<pre><var>N</var> <var>M</var>
|
||||
<var>x_1</var> <var>y_1</var> <var>z_1</var>
|
||||
<var>x_2</var> <var>y_2</var> <var>z_2</var>
|
||||
<var>:</var> <var>:</var>
|
||||
<var>x_N</var> <var>y_N</var> <var>z_N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力</h3>
|
||||
<p>りんごさんが選ぶケーキの (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) の最大値を出力しなさい. </p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 1</h3><pre>5 3
|
||||
3 1 4
|
||||
1 5 9
|
||||
2 6 5
|
||||
3 5 8
|
||||
9 7 9
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 1</h3><pre>56
|
||||
</pre>
|
||||
|
||||
<p><var>2, 4, 5</var> 種類目のケーキを食べることを考える. そのとき, 「綺麗さ」「おいしさ」「人気度」の合計はそれぞれ次のようになる. </p>
|
||||
<ul>
|
||||
<li>綺麗さ:<var>1 + 3 + 9 = 13</var></li>
|
||||
<li>おいしさ:<var>5 + 5 + 7 = 17</var></li>
|
||||
<li>人気度:<var>9 + 8 + 9 = 26</var></li>
|
||||
</ul>
|
||||
<p>このときの (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) は <var>13 + 17 + 26 = 56</var> となり, これが最大になる. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 2</h3><pre>5 3
|
||||
1 -2 3
|
||||
-4 5 -6
|
||||
7 -8 -9
|
||||
-10 11 -12
|
||||
13 -14 15
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 2</h3><pre>54
|
||||
</pre>
|
||||
|
||||
<p><var>1, 3, 5</var> 種類目のケーキを食べることを考える. そのとき, 「綺麗さ」「おいしさ」「人気度」の合計はそれぞれ次のようになる. </p>
|
||||
<ul>
|
||||
<li>綺麗さ:<var>1 + 7 + 13 = 21</var></li>
|
||||
<li>おいしさ:<var>(-2) + (-8) + (-14) = -24</var></li>
|
||||
<li>人気度:<var>3 + (-9) + 15 = 9</var></li>
|
||||
</ul>
|
||||
<p>このときの (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) は <var>21 + 24 + 9 = 54</var> となり, これが最大になる. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 3</h3><pre>10 5
|
||||
10 -80 21
|
||||
23 8 38
|
||||
-94 28 11
|
||||
-26 -2 18
|
||||
-69 72 79
|
||||
-26 -86 -54
|
||||
-72 -50 59
|
||||
21 65 -32
|
||||
40 -94 87
|
||||
-62 18 82
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 3</h3><pre>638
|
||||
</pre>
|
||||
|
||||
<p><var>3, 4, 5, 7, 10</var> 種類目のケーキを食べると, 綺麗さの合計は <var>-323</var>, おいしさの合計は <var>66</var>, 人気度の合計は <var>249</var> となる.<br />
|
||||
このときの (綺麗さの合計の絶対値) + (おいしさの合計の絶対値) + (人気度の合計の絶対値) は <var>323 + 66 + 249 = 638</var> となり, これが最大になる. </p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>入力例 4</h3><pre>3 2
|
||||
2000000000 -9000000000 4000000000
|
||||
7000000000 -5000000000 3000000000
|
||||
6000000000 -1000000000 8000000000
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>出力例 4</h3><pre>30000000000
|
||||
</pre>
|
||||
|
||||
<p>ケーキの綺麗さ, おいしさ, 人気度や出力すべき値が, 32bit 整数に収まらない場合もある. </p></section>
|
||||
</div>
|
||||
</span>
|
||||
<span class="lang-en">
|
||||
<p>Score: <var>400</var> points</p>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Problem Statement</h3>
|
||||
<p>Takahashi became a pastry chef and opened a shop <em>La Confiserie d'ABC</em> to celebrate AtCoder Beginner Contest 100.</p>
|
||||
<p>The shop sells <var>N</var> kinds of cakes.<br />
|
||||
Each kind of cake has three parameters "beauty", "tastiness" and "popularity". The <var>i</var>-th kind of cake has the beauty of <var>x_i</var>, the tastiness of <var>y_i</var> and the popularity of <var>z_i</var>.<br />
|
||||
These values may be zero or negative.</p>
|
||||
<p>Ringo has decided to have <var>M</var> pieces of cakes here. He will choose the set of cakes as follows:</p>
|
||||
<ul>
|
||||
<li>Do not have two or more pieces of the same kind of cake.</li>
|
||||
<li>Under the condition above, choose the set of cakes to maximize (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity).</li>
|
||||
</ul>
|
||||
<p>Find the maximum possible value of (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity) for the set of cakes that Ringo chooses.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Constraints</h3>
|
||||
<ul>
|
||||
<li><var>N</var> is an integer between <var>1</var> and <var>1 \ 000</var> (inclusive).</li>
|
||||
<li><var>M</var> is an integer between <var>0</var> and <var>N</var> (inclusive).</li>
|
||||
<li><var>x_i, y_i, z_i \ (1 \leq i \leq N)</var> are integers between <var>-10 \ 000 \ 000 \ 000</var> and <var>10 \ 000 \ 000 \ 000</var> (inclusive).</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="io-style">
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Input</h3>
|
||||
<p>Input is given from Standard Input in the following format:</p>
|
||||
<pre><var>N</var> <var>M</var>
|
||||
<var>x_1</var> <var>y_1</var> <var>z_1</var>
|
||||
<var>x_2</var> <var>y_2</var> <var>z_2</var>
|
||||
<var>:</var> <var>:</var>
|
||||
<var>x_N</var> <var>y_N</var> <var>z_N</var>
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Output</h3>
|
||||
<p>Print the maximum possible value of (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity) for the set of cakes that Ringo chooses.</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 1</h3><pre>5 3
|
||||
3 1 4
|
||||
1 5 9
|
||||
2 6 5
|
||||
3 5 8
|
||||
9 7 9
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 1</h3><pre>56
|
||||
</pre>
|
||||
|
||||
<p>Consider having the <var>2</var>-nd, <var>4</var>-th and <var>5</var>-th kinds of cakes. The total beauty, tastiness and popularity will be as follows:</p>
|
||||
<ul>
|
||||
<li>Beauty: <var>1 + 3 + 9 = 13</var></li>
|
||||
<li>Tastiness: <var>5 + 5 + 7 = 17</var></li>
|
||||
<li>Popularity: <var>9 + 8 + 9 = 26</var></li>
|
||||
</ul>
|
||||
<p>The value (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity) here is <var>13 + 17 + 26 = 56</var>. This is the maximum value.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 2</h3><pre>5 3
|
||||
1 -2 3
|
||||
-4 5 -6
|
||||
7 -8 -9
|
||||
-10 11 -12
|
||||
13 -14 15
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 2</h3><pre>54
|
||||
</pre>
|
||||
|
||||
<p>Consider having the <var>1</var>-st, <var>3</var>-rd and <var>5</var>-th kinds of cakes. The total beauty, tastiness and popularity will be as follows:</p>
|
||||
<ul>
|
||||
<li>Beauty: <var>1 + 7 + 13 = 21</var></li>
|
||||
<li>Tastiness: <var>(-2) + (-8) + (-14) = -24</var></li>
|
||||
<li>Popularity: <var>3 + (-9) + 15 = 9</var></li>
|
||||
</ul>
|
||||
<p>The value (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity) here is <var>21 + 24 + 9 = 54</var>. This is the maximum value.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 3</h3><pre>10 5
|
||||
10 -80 21
|
||||
23 8 38
|
||||
-94 28 11
|
||||
-26 -2 18
|
||||
-69 72 79
|
||||
-26 -86 -54
|
||||
-72 -50 59
|
||||
21 65 -32
|
||||
40 -94 87
|
||||
-62 18 82
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 3</h3><pre>638
|
||||
</pre>
|
||||
|
||||
<p>If we have the <var>3</var>-rd, <var>4</var>-th, <var>5</var>-th, <var>7</var>-th and <var>10</var>-th kinds of cakes, the total beauty, tastiness and popularity will be <var>-323</var>, <var>66</var> and <var>249</var>, respectively.<br />
|
||||
The value (the absolute value of the total beauty) + (the absolute value of the total tastiness) + (the absolute value of the total popularity) here is <var>323 + 66 + 249 = 638</var>. This is the maximum value.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Input 4</h3><pre>3 2
|
||||
2000000000 -9000000000 4000000000
|
||||
7000000000 -5000000000 3000000000
|
||||
6000000000 -1000000000 8000000000
|
||||
</pre>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="part">
|
||||
<section>
|
||||
<h3>Sample Output 4</h3><pre>30000000000
|
||||
</pre>
|
||||
|
||||
<p>The values of the beauty, tastiness and popularity of the cakes and the value to be printed may not fit into 32-bit integers.</p></section>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
|
||||
<div class="a2a_kit a2a_kit_size_20 a2a_default_style pull-right" data-a2a-url="https://atcoder.jp/contests/abc100/tasks/abc100_d?lang=en" data-a2a-title="D - Patisserie ABC">
|
||||
<a class="a2a_button_facebook"></a>
|
||||
<a class="a2a_button_twitter"></a>
|
||||
|
||||
<a class="a2a_button_telegram"></a>
|
||||
|
||||
<a class="a2a_dd" href="https://www.addtoany.com/share"></a>
|
||||
</div>
|
||||
|
||||
|
||||
<script async src="//static.addtoany.com/menu/page.js"></script>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 80px;">
|
||||
<footer class="footer">
|
||||
|
||||
<ul>
|
||||
<li><a href="/contests/abc100/rules">Rule</a></li>
|
||||
<li><a href="/contests/abc100/glossary">Glossary</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><a href="/tos">Terms of service</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/personal">Information Protection Policy</a></li>
|
||||
<li><a href="/company">Company</a></li>
|
||||
<li><a href="/faq">FAQ</a></li>
|
||||
<li><a href="/contact">Contact</a></li>
|
||||
|
||||
</ul>
|
||||
<div class="text-center">
|
||||
<small id="copyright">Copyright Since 2012 ©<a href="http://atcoder.co.jp">AtCoder Inc.</a> All rights reserved.</small>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<p id="fixed-server-timer" class="contest-timer"></p>
|
||||
<div id="scroll-page-top" style="display:none;"><span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span> Page Top</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
8210
tests/fixtures/codeforces_1550_A.html
vendored
Normal file
8210
tests/fixtures/codeforces_1550_A.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
4724
tests/fixtures/codeforces_1550_B.html
vendored
Normal file
4724
tests/fixtures/codeforces_1550_B.html
vendored
Normal file
File diff suppressed because it is too large
Load diff
1095
tests/fixtures/codeforces_1550_problems.html
vendored
Normal file
1095
tests/fixtures/codeforces_1550_problems.html
vendored
Normal file
File diff suppressed because one or more lines are too long
10
tests/fixtures/codeforces_contests.html
vendored
Normal file
10
tests/fixtures/codeforces_contests.html
vendored
Normal file
File diff suppressed because one or more lines are too long
43
tests/fixtures/cses_contests.html
vendored
Normal file
43
tests/fixtures/cses_contests.html
vendored
Normal file
File diff suppressed because one or more lines are too long
156
tests/fixtures/cses_task_1068.html
vendored
Normal file
156
tests/fixtures/cses_task_1068.html
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet " type="text/css" href="/cses.css?0" id="styles" />
|
||||
<link
|
||||
rel="stylesheet alternate"
|
||||
type="text/css"
|
||||
href="/cses-dark.css?0"
|
||||
id="styles-dark"
|
||||
/>
|
||||
<meta name="theme-color" content="white" id="theme-color" />
|
||||
<script type="application/json" id="darkmode-enabled">
|
||||
false
|
||||
</script>
|
||||
<script src="/ui.js"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="/lib/fontawesome/css/all.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body class="with-sidebar">
|
||||
<div class="header">
|
||||
<div>
|
||||
<a href="/" class="logo"><img src="/logo.png?1" alt="CSES" /></a>
|
||||
<a
|
||||
class="menu-toggle"
|
||||
onclick="document.body.classList.toggle('menu-open');"
|
||||
>
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
<div class="controls">
|
||||
<a class="account" href="/login">Login</a>
|
||||
<span>—</span>
|
||||
<a
|
||||
href="/darkmode"
|
||||
title="Toggle dark mode"
|
||||
onclick="return toggle_theme()"
|
||||
><i aria-label="Dark mode" class="fas fa-adjust"></i
|
||||
><span>Dark mode</span></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton">
|
||||
<div class="navigation">
|
||||
<div class="title-block">
|
||||
<h3><a href="/problemset/list/">CSES Problem Set</a></h3>
|
||||
<h1>Weird Algorithm</h1>
|
||||
<ul class="nav">
|
||||
<li><a href="/problemset/task/1068/" class="current">Task</a></li>
|
||||
<li><a href="/problemset/stats/1068/">Statistics</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
<title>CSES - Weird Algorithm</title
|
||||
><link rel="stylesheet" href="/lib/katex/katex.min.css" />
|
||||
<script defer src="/lib/katex/katex.min.js"></script>
|
||||
<script defer src="/lib/katex/contrib/copy-tex.min.js"></script>
|
||||
<script
|
||||
defer
|
||||
src="/lib/google-code-prettify/run_prettify.js"
|
||||
></script>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded', function (e) {
|
||||
const mathElements = document.getElementsByClassName('math')
|
||||
const macros = {}
|
||||
for (let element of mathElements) {
|
||||
katex.render(element.textContent, element, {
|
||||
displayMode: element.classList.contains('math-display'),
|
||||
throwOnError: false,
|
||||
globalGroup: true,
|
||||
macros
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<ul class="task-constraints">
|
||||
<li><b>Time limit:</b> 1.00 s</li>
|
||||
<li><b>Memory limit:</b> 512 MB</li>
|
||||
</ul>
|
||||
<div class="md">
|
||||
<p>
|
||||
Consider an algorithm that takes as input a positive integer
|
||||
<span class="math math-inline">n</span>. If
|
||||
<span class="math math-inline">n</span> is even, the algorithm
|
||||
divides it by two, and if
|
||||
<span class="math math-inline">n</span> is odd, the algorithm
|
||||
multiplies it by three and adds one. The algorithm repeats this,
|
||||
until <span class="math math-inline">n</span> is one. For example,
|
||||
the sequence for <span class="math math-inline">n=3</span> is as
|
||||
follows:
|
||||
<span class="math math-display">
|
||||
3 \rightarrow 10 \rightarrow 5 \rightarrow 16 \rightarrow 8
|
||||
\rightarrow 4 \rightarrow 2 \rightarrow 1</span
|
||||
>
|
||||
Your task is to simulate the execution of the algorithm for a
|
||||
given value of <span class="math math-inline">n</span>.
|
||||
</p>
|
||||
<h1 id="input">Input</h1>
|
||||
<p>
|
||||
The only input line contains an integer
|
||||
<span class="math math-inline">n</span>.
|
||||
</p>
|
||||
<h1 id="output">Output</h1>
|
||||
<p>
|
||||
Print a line that contains all values of
|
||||
<span class="math math-inline">n</span> during the algorithm.
|
||||
</p>
|
||||
<h1 id="constraints">Constraints</h1>
|
||||
<ul>
|
||||
<li><span class="math math-inline">1 \le n \le 10^6</span></li>
|
||||
</ul>
|
||||
<h1 id="example">Example</h1>
|
||||
<p>Input:</p>
|
||||
<pre>
|
||||
3
|
||||
</pre
|
||||
>
|
||||
<p>Output:</p>
|
||||
<pre>
|
||||
3 10 5 16 8 4 2 1
|
||||
</pre
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav sidebar">
|
||||
<h4>Introductory Problems</h4>
|
||||
<a class="current" href="/problemset/task/1068"
|
||||
>Weird Algorithm<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1083"
|
||||
>Missing Number<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1069"
|
||||
>Repetitions<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1094"
|
||||
>Increasing Array<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1070"
|
||||
>Permutations<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1071"
|
||||
>Number Spiral<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1072"
|
||||
>Two Knights<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1092"
|
||||
>Two Sets<span class="task-score icon"></span></a
|
||||
>...
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
150
tests/fixtures/cses_task_1621.html
vendored
Normal file
150
tests/fixtures/cses_task_1621.html
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<link rel="stylesheet " type="text/css" href="/cses.css?0" id="styles" />
|
||||
<link
|
||||
rel="stylesheet alternate"
|
||||
type="text/css"
|
||||
href="/cses-dark.css?0"
|
||||
id="styles-dark"
|
||||
/>
|
||||
<meta name="theme-color" content="white" id="theme-color" />
|
||||
<script type="application/json" id="darkmode-enabled">
|
||||
false
|
||||
</script>
|
||||
<script src="/ui.js"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="/lib/fontawesome/css/all.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body class="with-sidebar">
|
||||
<div class="header">
|
||||
<div>
|
||||
<a href="/" class="logo"><img src="/logo.png?1" alt="CSES" /></a>
|
||||
<a
|
||||
class="menu-toggle"
|
||||
onclick="document.body.classList.toggle('menu-open');"
|
||||
>
|
||||
<i class="fas fa-bars"></i>
|
||||
</a>
|
||||
<div class="controls">
|
||||
<a class="account" href="/login">Login</a>
|
||||
<span>—</span>
|
||||
<a
|
||||
href="/darkmode"
|
||||
title="Toggle dark mode"
|
||||
onclick="return toggle_theme()"
|
||||
><i aria-label="Dark mode" class="fas fa-adjust"></i
|
||||
><span>Dark mode</span></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton">
|
||||
<div class="navigation">
|
||||
<div class="title-block">
|
||||
<h3><a href="/problemset/list/">CSES Problem Set</a></h3>
|
||||
<h1>Distinct Numbers</h1>
|
||||
<ul class="nav">
|
||||
<li><a href="/problemset/task/1621/" class="current">Task</a></li>
|
||||
<li><a href="/problemset/stats/1621/">Statistics</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="content">
|
||||
<title>CSES - Distinct Numbers</title
|
||||
><link rel="stylesheet" href="/lib/katex/katex.min.css" />
|
||||
<script defer src="/lib/katex/katex.min.js"></script>
|
||||
<script defer src="/lib/katex/contrib/copy-tex.min.js"></script>
|
||||
<script
|
||||
defer
|
||||
src="/lib/google-code-prettify/run_prettify.js"
|
||||
></script>
|
||||
<script>
|
||||
addEventListener('DOMContentLoaded', function (e) {
|
||||
const mathElements = document.getElementsByClassName('math')
|
||||
const macros = {}
|
||||
for (let element of mathElements) {
|
||||
katex.render(element.textContent, element, {
|
||||
displayMode: element.classList.contains('math-display'),
|
||||
throwOnError: false,
|
||||
globalGroup: true,
|
||||
macros
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<ul class="task-constraints">
|
||||
<li><b>Time limit:</b> 1.00 s</li>
|
||||
<li><b>Memory limit:</b> 512 MB</li>
|
||||
</ul>
|
||||
<div class="md">
|
||||
<p>
|
||||
You are given a list of
|
||||
<span class="math math-inline">n</span> integers, and your task is
|
||||
to calculate the number of <em>distinct</em> values in the list.
|
||||
</p>
|
||||
<h1 id="input">Input</h1>
|
||||
<p>
|
||||
The first input line has an integer
|
||||
<span class="math math-inline">n</span>: the number of values.
|
||||
</p>
|
||||
<p>
|
||||
The second line has
|
||||
<span class="math math-inline">n</span> integers
|
||||
<span class="math math-inline">x_1,x_2,\dots,x_n</span>.
|
||||
</p>
|
||||
<h1 id="output">Output</h1>
|
||||
<p>Print one integers: the number of distinct values.</p>
|
||||
<h1 id="constraints">Constraints</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<span class="math math-inline">1 \le n \le 2 \cdot 10^5</span>
|
||||
</li>
|
||||
<li><span class="math math-inline">1 \le x_i \le 10^9</span></li>
|
||||
</ul>
|
||||
<h1 id="example">Example</h1>
|
||||
<p>Input:</p>
|
||||
<pre>
|
||||
5
|
||||
2 3 2 2 3
|
||||
</pre
|
||||
>
|
||||
<p>Output:</p>
|
||||
<pre>
|
||||
2
|
||||
</pre
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav sidebar">
|
||||
<h4>Sorting and Searching</h4>
|
||||
<a class="current" href="/problemset/task/1621"
|
||||
>Distinct Numbers<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1084"
|
||||
>Apartments<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1090"
|
||||
>Ferris Wheel<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1091"
|
||||
>Concert Tickets<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1619"
|
||||
>Restaurant Customers<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1629"
|
||||
>Movie Festival<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1640"
|
||||
>Sum of Two Values<span class="task-score icon"></span></a
|
||||
><a href="/problemset/task/1643"
|
||||
>Maximum Subarray Sum<span class="task-score icon"></span></a
|
||||
>...
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
def test():
|
||||
assert 5 == 5
|
||||
69
tests/test_scrapers.py
Normal file
69
tests/test_scrapers.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import pytest
|
||||
|
||||
from scrapers.models import (
|
||||
ContestListResult,
|
||||
MetadataResult,
|
||||
TestsResult,
|
||||
)
|
||||
|
||||
MODEL_FOR_MODE = {
|
||||
"metadata": MetadataResult,
|
||||
"contests": ContestListResult,
|
||||
}
|
||||
|
||||
MATRIX = {
|
||||
"cses": {
|
||||
"metadata": ("introductory_problems",),
|
||||
"tests": ("introductory_problems",),
|
||||
"contests": tuple(),
|
||||
},
|
||||
"atcoder": {
|
||||
"metadata": ("abc100",),
|
||||
"tests": ("abc100",),
|
||||
"contests": tuple(),
|
||||
},
|
||||
"codeforces": {
|
||||
"metadata": ("1550",),
|
||||
"tests": ("1550",),
|
||||
"contests": tuple(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("scraper", MATRIX.keys())
|
||||
@pytest.mark.parametrize("mode", ["metadata", "tests", "contests"])
|
||||
def test_scraper_offline_fixture_matrix(run_scraper_offline, scraper, mode):
|
||||
args = MATRIX[scraper][mode]
|
||||
rc, objs = run_scraper_offline(scraper, mode, *args)
|
||||
assert rc in (0, 1), f"Bad exit code {rc}"
|
||||
assert objs, f"No JSON output for {scraper}:{mode}"
|
||||
|
||||
if mode in ("metadata", "contests"):
|
||||
Model = MODEL_FOR_MODE[mode]
|
||||
model = Model.model_validate(objs[-1])
|
||||
assert model is not None
|
||||
if mode == "metadata":
|
||||
assert model.success in (True, False)
|
||||
if model.success:
|
||||
assert len(model.problems) >= 1
|
||||
assert all(isinstance(p.id, str) and p.id for p in model.problems)
|
||||
else:
|
||||
assert model.success in (True, False)
|
||||
if model.success:
|
||||
assert len(model.contests) >= 1
|
||||
else:
|
||||
validated_any = False
|
||||
for obj in objs:
|
||||
if "success" in obj and "tests" in obj and "problem_id" in obj:
|
||||
tr = TestsResult.model_validate(obj)
|
||||
assert tr.problem_id != ""
|
||||
assert isinstance(tr.tests, list)
|
||||
validated_any = True
|
||||
else:
|
||||
assert "problem_id" in obj
|
||||
assert "tests" in obj and isinstance(obj["tests"], list)
|
||||
assert (
|
||||
"timeout_ms" in obj and "memory_mb" in obj and "interactive" in obj
|
||||
)
|
||||
validated_any = True
|
||||
assert validated_any, "No valid tests payloads validated"
|
||||
103
uv.lock
generated
103
uv.lock
generated
|
|
@ -92,6 +92,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.11.0"
|
||||
|
|
@ -1299,6 +1308,86 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/54/ecab642b3bed45f7d5f59b38443dcb36ef50f85af192e6ece103dbfe9587/pydantic-2.11.10.tar.gz", hash = "sha256:dc280f0982fbda6c38fada4e476dc0a4f3aeaf9c6ad4c28df68a666ec3c61423", size = 788494, upload-time = "2025-10-04T10:40:41.338Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/1f/73c53fcbfb0b5a78f91176df41945ca466e71e9d9d836e5c522abda39ee7/pydantic-2.11.10-py3-none-any.whl", hash = "sha256:802a655709d49bd004c31e865ef37da30b540786a46bfce02333e0e24b5fe29a", size = 444823, upload-time = "2025-10-04T10:40:39.055Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyee"
|
||||
version = "13.0.0"
|
||||
|
|
@ -1460,6 +1549,7 @@ dependencies = [
|
|||
{ name = "curl-cffi" },
|
||||
{ name = "httpx" },
|
||||
{ name = "ndjson" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "requests" },
|
||||
{ name = "scrapling", extra = ["fetchers"] },
|
||||
]
|
||||
|
|
@ -1482,6 +1572,7 @@ requires-dist = [
|
|||
{ name = "curl-cffi", specifier = ">=0.13.0" },
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "ndjson", specifier = ">=0.3.1" },
|
||||
{ name = "pydantic", specifier = ">=2.11.10" },
|
||||
{ name = "requests", specifier = ">=2.32.5" },
|
||||
{ name = "scrapling", extras = ["fetchers"], specifier = ">=0.3.5" },
|
||||
]
|
||||
|
|
@ -1623,6 +1714,18 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ua-parser"
|
||||
version = "1.0.1"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue