From fc3b1f9c48e140b725893f6852ed2d2e2ccf967f Mon Sep 17 00:00:00 2001 From: arthur Date: Wed, 10 Dec 2025 09:52:19 -0300 Subject: [PATCH] feat: new problem formatted --- edit-distance/Makefile | 97 + edit-distance/edit-distance.pdf | Bin 0 -> 77482 bytes edit-distance/edit-distance.tex | 42 + edit-distance/input/1 | 2 + edit-distance/input/10 | 2 + edit-distance/input/100 | 2 + edit-distance/input/101 | 2 + edit-distance/input/102 | 2 + edit-distance/input/103 | 2 + edit-distance/input/11 | 2 + edit-distance/input/12 | 2 + edit-distance/input/13 | 2 + edit-distance/input/14 | 2 + edit-distance/input/15 | 2 + edit-distance/input/16 | 2 + edit-distance/input/17 | 2 + edit-distance/input/18 | 2 + edit-distance/input/19 | 2 + edit-distance/input/2 | 2 + edit-distance/input/20 | 2 + edit-distance/input/21 | 2 + edit-distance/input/22 | 2 + edit-distance/input/23 | 2 + edit-distance/input/24 | 2 + edit-distance/input/25 | 2 + edit-distance/input/26 | 2 + edit-distance/input/27 | 2 + edit-distance/input/28 | 2 + edit-distance/input/29 | 2 + edit-distance/input/3 | 2 + edit-distance/input/30 | 2 + edit-distance/input/31 | 2 + edit-distance/input/32 | 2 + edit-distance/input/33 | 2 + edit-distance/input/34 | 2 + edit-distance/input/35 | 2 + edit-distance/input/36 | 2 + edit-distance/input/37 | 2 + edit-distance/input/38 | 2 + edit-distance/input/39 | 2 + edit-distance/input/4 | 2 + edit-distance/input/40 | 2 + edit-distance/input/41 | 2 + edit-distance/input/42 | 2 + edit-distance/input/43 | 2 + edit-distance/input/44 | 2 + edit-distance/input/45 | 2 + edit-distance/input/46 | 2 + edit-distance/input/47 | 2 + edit-distance/input/48 | 2 + edit-distance/input/49 | 2 + edit-distance/input/5 | 2 + edit-distance/input/50 | 2 + edit-distance/input/51 | 2 + edit-distance/input/52 | 2 + edit-distance/input/53 | 2 + edit-distance/input/54 | 2 + edit-distance/input/55 | 2 + edit-distance/input/56 | 2 + edit-distance/input/57 | 2 + edit-distance/input/58 | 2 + edit-distance/input/59 | 2 + edit-distance/input/6 | 2 + edit-distance/input/60 | 2 + edit-distance/input/61 | 2 + edit-distance/input/62 | 2 + edit-distance/input/63 | 2 + edit-distance/input/64 | 2 + edit-distance/input/65 | 2 + edit-distance/input/66 | 2 + edit-distance/input/67 | 2 + edit-distance/input/68 | 2 + edit-distance/input/69 | 2 + edit-distance/input/7 | 2 + edit-distance/input/70 | 2 + edit-distance/input/71 | 2 + edit-distance/input/72 | 2 + edit-distance/input/73 | 2 + edit-distance/input/74 | 2 + edit-distance/input/75 | 2 + edit-distance/input/76 | 2 + edit-distance/input/77 | 2 + edit-distance/input/78 | 2 + edit-distance/input/79 | 2 + edit-distance/input/8 | 2 + edit-distance/input/80 | 2 + edit-distance/input/81 | 2 + edit-distance/input/82 | 2 + edit-distance/input/83 | 2 + edit-distance/input/84 | 2 + edit-distance/input/85 | 2 + edit-distance/input/86 | 2 + edit-distance/input/87 | 2 + edit-distance/input/88 | 2 + edit-distance/input/89 | 2 + edit-distance/input/9 | 2 + edit-distance/input/90 | 2 + edit-distance/input/91 | 2 + edit-distance/input/92 | 2 + edit-distance/input/93 | 2 + edit-distance/input/94 | 2 + edit-distance/input/95 | 2 + edit-distance/input/96 | 2 + edit-distance/input/97 | 2 + edit-distance/input/98 | 2 + edit-distance/input/99 | 2 + edit-distance/maratona.cls | 188 + edit-distance/output/1 | 1 + edit-distance/output/10 | 1 + edit-distance/output/100 | 1 + edit-distance/output/101 | 1 + edit-distance/output/102 | 1 + edit-distance/output/103 | 1 + edit-distance/output/11 | 1 + edit-distance/output/12 | 1 + edit-distance/output/13 | 1 + edit-distance/output/14 | 1 + edit-distance/output/15 | 1 + edit-distance/output/16 | 1 + edit-distance/output/17 | 1 + edit-distance/output/18 | 1 + edit-distance/output/19 | 1 + edit-distance/output/2 | 1 + edit-distance/output/20 | 1 + edit-distance/output/21 | 1 + edit-distance/output/22 | 1 + edit-distance/output/23 | 1 + edit-distance/output/24 | 1 + edit-distance/output/25 | 1 + edit-distance/output/26 | 1 + edit-distance/output/27 | 1 + edit-distance/output/28 | 1 + edit-distance/output/29 | 1 + edit-distance/output/3 | 1 + edit-distance/output/30 | 1 + edit-distance/output/31 | 1 + edit-distance/output/32 | 1 + edit-distance/output/33 | 1 + edit-distance/output/34 | 1 + edit-distance/output/35 | 1 + edit-distance/output/36 | 1 + edit-distance/output/37 | 1 + edit-distance/output/38 | 1 + edit-distance/output/39 | 1 + edit-distance/output/4 | 1 + edit-distance/output/40 | 1 + edit-distance/output/41 | 1 + edit-distance/output/42 | 1 + edit-distance/output/43 | 1 + edit-distance/output/44 | 1 + edit-distance/output/45 | 1 + edit-distance/output/46 | 1 + edit-distance/output/47 | 1 + edit-distance/output/48 | 1 + edit-distance/output/49 | 1 + edit-distance/output/5 | 1 + edit-distance/output/50 | 1 + edit-distance/output/51 | 1 + edit-distance/output/52 | 1 + edit-distance/output/53 | 1 + edit-distance/output/54 | 1 + edit-distance/output/55 | 1 + edit-distance/output/56 | 1 + edit-distance/output/57 | 1 + edit-distance/output/58 | 1 + edit-distance/output/59 | 1 + edit-distance/output/6 | 1 + edit-distance/output/60 | 1 + edit-distance/output/61 | 1 + edit-distance/output/62 | 1 + edit-distance/output/63 | 1 + edit-distance/output/64 | 1 + edit-distance/output/65 | 1 + edit-distance/output/66 | 1 + edit-distance/output/67 | 1 + edit-distance/output/68 | 1 + edit-distance/output/69 | 1 + edit-distance/output/7 | 1 + edit-distance/output/70 | 1 + edit-distance/output/71 | 1 + edit-distance/output/72 | 1 + edit-distance/output/73 | 1 + edit-distance/output/74 | 1 + edit-distance/output/75 | 1 + edit-distance/output/76 | 1 + edit-distance/output/77 | 1 + edit-distance/output/78 | 1 + edit-distance/output/79 | 1 + edit-distance/output/8 | 1 + edit-distance/output/80 | 1 + edit-distance/output/81 | 1 + edit-distance/output/82 | 1 + edit-distance/output/83 | 1 + edit-distance/output/84 | 1 + edit-distance/output/85 | 1 + edit-distance/output/86 | 1 + edit-distance/output/87 | 1 + edit-distance/output/88 | 1 + edit-distance/output/89 | 1 + edit-distance/output/9 | 1 + edit-distance/output/90 | 1 + edit-distance/output/91 | 1 + edit-distance/output/92 | 1 + edit-distance/output/93 | 1 + edit-distance/output/94 | 1 + edit-distance/output/95 | 1 + edit-distance/output/96 | 1 + edit-distance/output/97 | 1 + edit-distance/output/98 | 1 + edit-distance/output/99 | 1 + edit-distance/problem.json | 64 + edit-distance/src/TLE.cpp | 32 + edit-distance/src/ac.cpp | 48 + edit-distance/src/checker.cpp | 17 + edit-distance/src/generator.cpp | 82 + edit-distance/src/script.sh | 1 + edit-distance/src/testlib.h | 5963 +++++++++++++++++++++++ edit-distance/src/validator.cpp | 19 + edit-distance/statement/description.tex | 11 + edit-distance/statement/input.tex | 6 + edit-distance/statement/notes.tex | 0 edit-distance/statement/output.tex | 1 + edit-distance/statement/preamble.tex | 0 edit-distance/statement/tutorial.tex | 0 224 files changed, 6880 insertions(+) create mode 100644 edit-distance/Makefile create mode 100644 edit-distance/edit-distance.pdf create mode 100644 edit-distance/edit-distance.tex create mode 100644 edit-distance/input/1 create mode 100644 edit-distance/input/10 create mode 100644 edit-distance/input/100 create mode 100644 edit-distance/input/101 create mode 100644 edit-distance/input/102 create mode 100644 edit-distance/input/103 create mode 100644 edit-distance/input/11 create mode 100644 edit-distance/input/12 create mode 100644 edit-distance/input/13 create mode 100644 edit-distance/input/14 create mode 100644 edit-distance/input/15 create mode 100644 edit-distance/input/16 create mode 100644 edit-distance/input/17 create mode 100644 edit-distance/input/18 create mode 100644 edit-distance/input/19 create mode 100644 edit-distance/input/2 create mode 100644 edit-distance/input/20 create mode 100644 edit-distance/input/21 create mode 100644 edit-distance/input/22 create mode 100644 edit-distance/input/23 create mode 100644 edit-distance/input/24 create mode 100644 edit-distance/input/25 create mode 100644 edit-distance/input/26 create mode 100644 edit-distance/input/27 create mode 100644 edit-distance/input/28 create mode 100644 edit-distance/input/29 create mode 100644 edit-distance/input/3 create mode 100644 edit-distance/input/30 create mode 100644 edit-distance/input/31 create mode 100644 edit-distance/input/32 create mode 100644 edit-distance/input/33 create mode 100644 edit-distance/input/34 create mode 100644 edit-distance/input/35 create mode 100644 edit-distance/input/36 create mode 100644 edit-distance/input/37 create mode 100644 edit-distance/input/38 create mode 100644 edit-distance/input/39 create mode 100644 edit-distance/input/4 create mode 100644 edit-distance/input/40 create mode 100644 edit-distance/input/41 create mode 100644 edit-distance/input/42 create mode 100644 edit-distance/input/43 create mode 100644 edit-distance/input/44 create mode 100644 edit-distance/input/45 create mode 100644 edit-distance/input/46 create mode 100644 edit-distance/input/47 create mode 100644 edit-distance/input/48 create mode 100644 edit-distance/input/49 create mode 100644 edit-distance/input/5 create mode 100644 edit-distance/input/50 create mode 100644 edit-distance/input/51 create mode 100644 edit-distance/input/52 create mode 100644 edit-distance/input/53 create mode 100644 edit-distance/input/54 create mode 100644 edit-distance/input/55 create mode 100644 edit-distance/input/56 create mode 100644 edit-distance/input/57 create mode 100644 edit-distance/input/58 create mode 100644 edit-distance/input/59 create mode 100644 edit-distance/input/6 create mode 100644 edit-distance/input/60 create mode 100644 edit-distance/input/61 create mode 100644 edit-distance/input/62 create mode 100644 edit-distance/input/63 create mode 100644 edit-distance/input/64 create mode 100644 edit-distance/input/65 create mode 100644 edit-distance/input/66 create mode 100644 edit-distance/input/67 create mode 100644 edit-distance/input/68 create mode 100644 edit-distance/input/69 create mode 100644 edit-distance/input/7 create mode 100644 edit-distance/input/70 create mode 100644 edit-distance/input/71 create mode 100644 edit-distance/input/72 create mode 100644 edit-distance/input/73 create mode 100644 edit-distance/input/74 create mode 100644 edit-distance/input/75 create mode 100644 edit-distance/input/76 create mode 100644 edit-distance/input/77 create mode 100644 edit-distance/input/78 create mode 100644 edit-distance/input/79 create mode 100644 edit-distance/input/8 create mode 100644 edit-distance/input/80 create mode 100644 edit-distance/input/81 create mode 100644 edit-distance/input/82 create mode 100644 edit-distance/input/83 create mode 100644 edit-distance/input/84 create mode 100644 edit-distance/input/85 create mode 100644 edit-distance/input/86 create mode 100644 edit-distance/input/87 create mode 100644 edit-distance/input/88 create mode 100644 edit-distance/input/89 create mode 100644 edit-distance/input/9 create mode 100644 edit-distance/input/90 create mode 100644 edit-distance/input/91 create mode 100644 edit-distance/input/92 create mode 100644 edit-distance/input/93 create mode 100644 edit-distance/input/94 create mode 100644 edit-distance/input/95 create mode 100644 edit-distance/input/96 create mode 100644 edit-distance/input/97 create mode 100644 edit-distance/input/98 create mode 100644 edit-distance/input/99 create mode 100644 edit-distance/maratona.cls create mode 100644 edit-distance/output/1 create mode 100644 edit-distance/output/10 create mode 100644 edit-distance/output/100 create mode 100644 edit-distance/output/101 create mode 100644 edit-distance/output/102 create mode 100644 edit-distance/output/103 create mode 100644 edit-distance/output/11 create mode 100644 edit-distance/output/12 create mode 100644 edit-distance/output/13 create mode 100644 edit-distance/output/14 create mode 100644 edit-distance/output/15 create mode 100644 edit-distance/output/16 create mode 100644 edit-distance/output/17 create mode 100644 edit-distance/output/18 create mode 100644 edit-distance/output/19 create mode 100644 edit-distance/output/2 create mode 100644 edit-distance/output/20 create mode 100644 edit-distance/output/21 create mode 100644 edit-distance/output/22 create mode 100644 edit-distance/output/23 create mode 100644 edit-distance/output/24 create mode 100644 edit-distance/output/25 create mode 100644 edit-distance/output/26 create mode 100644 edit-distance/output/27 create mode 100644 edit-distance/output/28 create mode 100644 edit-distance/output/29 create mode 100644 edit-distance/output/3 create mode 100644 edit-distance/output/30 create mode 100644 edit-distance/output/31 create mode 100644 edit-distance/output/32 create mode 100644 edit-distance/output/33 create mode 100644 edit-distance/output/34 create mode 100644 edit-distance/output/35 create mode 100644 edit-distance/output/36 create mode 100644 edit-distance/output/37 create mode 100644 edit-distance/output/38 create mode 100644 edit-distance/output/39 create mode 100644 edit-distance/output/4 create mode 100644 edit-distance/output/40 create mode 100644 edit-distance/output/41 create mode 100644 edit-distance/output/42 create mode 100644 edit-distance/output/43 create mode 100644 edit-distance/output/44 create mode 100644 edit-distance/output/45 create mode 100644 edit-distance/output/46 create mode 100644 edit-distance/output/47 create mode 100644 edit-distance/output/48 create mode 100644 edit-distance/output/49 create mode 100644 edit-distance/output/5 create mode 100644 edit-distance/output/50 create mode 100644 edit-distance/output/51 create mode 100644 edit-distance/output/52 create mode 100644 edit-distance/output/53 create mode 100644 edit-distance/output/54 create mode 100644 edit-distance/output/55 create mode 100644 edit-distance/output/56 create mode 100644 edit-distance/output/57 create mode 100644 edit-distance/output/58 create mode 100644 edit-distance/output/59 create mode 100644 edit-distance/output/6 create mode 100644 edit-distance/output/60 create mode 100644 edit-distance/output/61 create mode 100644 edit-distance/output/62 create mode 100644 edit-distance/output/63 create mode 100644 edit-distance/output/64 create mode 100644 edit-distance/output/65 create mode 100644 edit-distance/output/66 create mode 100644 edit-distance/output/67 create mode 100644 edit-distance/output/68 create mode 100644 edit-distance/output/69 create mode 100644 edit-distance/output/7 create mode 100644 edit-distance/output/70 create mode 100644 edit-distance/output/71 create mode 100644 edit-distance/output/72 create mode 100644 edit-distance/output/73 create mode 100644 edit-distance/output/74 create mode 100644 edit-distance/output/75 create mode 100644 edit-distance/output/76 create mode 100644 edit-distance/output/77 create mode 100644 edit-distance/output/78 create mode 100644 edit-distance/output/79 create mode 100644 edit-distance/output/8 create mode 100644 edit-distance/output/80 create mode 100644 edit-distance/output/81 create mode 100644 edit-distance/output/82 create mode 100644 edit-distance/output/83 create mode 100644 edit-distance/output/84 create mode 100644 edit-distance/output/85 create mode 100644 edit-distance/output/86 create mode 100644 edit-distance/output/87 create mode 100644 edit-distance/output/88 create mode 100644 edit-distance/output/89 create mode 100644 edit-distance/output/9 create mode 100644 edit-distance/output/90 create mode 100644 edit-distance/output/91 create mode 100644 edit-distance/output/92 create mode 100644 edit-distance/output/93 create mode 100644 edit-distance/output/94 create mode 100644 edit-distance/output/95 create mode 100644 edit-distance/output/96 create mode 100644 edit-distance/output/97 create mode 100644 edit-distance/output/98 create mode 100644 edit-distance/output/99 create mode 100644 edit-distance/problem.json create mode 100644 edit-distance/src/TLE.cpp create mode 100644 edit-distance/src/ac.cpp create mode 100644 edit-distance/src/checker.cpp create mode 100644 edit-distance/src/generator.cpp create mode 100644 edit-distance/src/script.sh create mode 100644 edit-distance/src/testlib.h create mode 100644 edit-distance/src/validator.cpp create mode 100644 edit-distance/statement/description.tex create mode 100644 edit-distance/statement/input.tex create mode 100644 edit-distance/statement/notes.tex create mode 100644 edit-distance/statement/output.tex create mode 100644 edit-distance/statement/preamble.tex create mode 100644 edit-distance/statement/tutorial.tex diff --git a/edit-distance/Makefile b/edit-distance/Makefile new file mode 100644 index 0000000..4227f1a --- /dev/null +++ b/edit-distance/Makefile @@ -0,0 +1,97 @@ +# Normal directories +SRC_DIR := src +BIN_DIR := bin +DBG_DIR := bin/debug + +# Grader directories +GRADER := $(wildcard $(SRC_DIR)/grader.cpp) +GRADER_DIR := $(SRC_DIR)/grader +HANDLER_DIR := $(SRC_DIR)/handler + +GRADER_SRC := $(wildcard $(GRADER_DIR)/*.cpp) +GRADER_BIN := $(patsubst $(GRADER_DIR)/%.cpp, $(BIN_DIR)/%, $(GRADER_SRC)) +GRADER_DBG := $(patsubst $(GRADER_DIR)/%.cpp, $(DBG_DIR)/%, $(GRADER_SRC)) + +# Change CPP source directories if grader is defined +ifdef GRADER + SRC := $(wildcard $(HANDLER_DIR)/*.cpp) + BIN := $(patsubst $(HANDLER_DIR)/%.cpp, $(BIN_DIR)/%, $(SRC)) + DBG := $(patsubst $(HANDLER_DIR)/%.cpp, $(DBG_DIR)/%, $(SRC)) +else + SRC := $(wildcard $(SRC_DIR)/*.cpp) + BIN := $(patsubst $(SRC_DIR)/%.cpp, $(BIN_DIR)/%, $(SRC)) + DBG := $(patsubst $(SRC_DIR)/%.cpp, $(DBG_DIR)/%, $(SRC)) +endif + +SRC_C := $(wildcard $(SRC_DIR)/*.c) +BIN_C := $(patsubst $(SRC_DIR)/%.c, $(BIN_DIR)/%, $(SRC_C)) +DBG_C := $(patsubst $(SRC_DIR)/%.c, $(DBG_DIR)/%, $(SRC_C)) + +SRC_JAVA := $(wildcard $(SRC_DIR)/*.java) +BIN_JAVA := $(patsubst $(SRC_DIR)/%.java, $(BIN_DIR)/%.class, $(SRC_JAVA)) +DBG_JAVA := $(patsubst $(SRC_DIR)/%.java, $(DBG_DIR)/%.class, $(SRC_JAVA)) + +CHECKER := $(wildcard $(SRC_DIR)/checker.cpp) + +C := gcc +CPP := g++ +CXX_FLAGS := -Wall -O2 +DEBUG_FLAGS := -Wall -g +BOCA_FLAGS := -static -DBOCA_SUPPORT + +JV = javac +JV_DEBUG = -g +JV_DIR = -d bin +JV_DBG_DIR = -d bin/debug + +.PHONY: all debug release checker clean + +all: debug release checker + +debug: $(DBG) $(DBG_C) $(DBG_JAVA) $(GRADER_DBG) + +release: $(BIN) $(BIN_C) $(BIN_JAVA) $(GRADER_BIN) + +ifdef CHECKER +checker: $(DBG_DIR)/checker-boca $(BIN_DIR)/checker-boca +endif + +$(BIN): $(BIN_DIR)/% : $(SRC_DIR)/%.cpp | $(BIN_DIR) + $(CPP) $(CXX_FLAGS) $^ -o $@ + +$(DBG): $(DBG_DIR)/% : $(SRC_DIR)/%.cpp | $(DBG_DIR) + $(CPP) $(DEBUG_FLAGS) $^ -o $@ + +$(BIN_C): $(BIN_DIR)/% : $(SRC_DIR)/%.c | $(BIN_DIR) + $(C) $(CXX_FLAGS) $^ -o $@ + +$(DBG_C): $(DBG_DIR)/% : $(SRC_DIR)/%.c | $(DBG_DIR) + $(C) $(DEBUG_FLAGS) $^ -o $@ + +$(BIN_JAVA): $(BIN_DIR)/%.class : $(SRC_DIR)/%.java | $(BIN_DIR) + $(JV) $(JV_DIR) $^ + +$(DBG_JAVA): $(DBG_DIR)/%.class : $(SRC_DIR)/%.java | $(DBG_DIR) + $(JV) $(JV_DEBUG) $(JV_DBG_DIR) $^ + +$(GRADER_BIN): $(BIN_DIR)/% : $(GRADER_DIR)/%.cpp $(GRADER) $(GRADER_DIR)/*.h + $(CPP) $(CXX_FLAGS) $^ -o $@ + +$(GRADER_DBG): $(DBG_DIR)/% : $(GRADER_DIR)/%.cpp $(GRADER) $(GRADER_DIR)/*.h + $(CPP) $(DEBUG_FLAGS) $^ -o $@ + +$(BIN_DIR): + mkdir -p $@ + +$(DBG_DIR): + mkdir -p $@ + +$(BIN_DIR)/checker-boca: $(SRC_DIR)/checker.cpp + $(CPP) $(CXX_FLAGS) $(BOCA_FLAGS) $^ -o $@ + +$(DBG_DIR)/checker-boca: $(SRC_DIR)/checker.cpp + $(CPP) $(DEBUG_FLAGS) $(BOCA_FLAGS) $^ -o $@ + +clean: + @echo Cleaning problem files + rm -rf bin diff --git a/edit-distance/edit-distance.pdf b/edit-distance/edit-distance.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c8227bd59b948be3435f51c639b4e18895e72b6c GIT binary patch literal 77482 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 Q-I|FBij-7DP88~Y0b5qGF8}}l literal 0 HcmV?d00001 diff --git a/edit-distance/edit-distance.tex b/edit-distance/edit-distance.tex new file mode 100644 index 0000000..0f66983 --- /dev/null +++ b/edit-distance/edit-distance.tex @@ -0,0 +1,42 @@ +\documentclass{maratona} + +\begin{document} +\begin{ProblemaAutor}{}{Distância de Edição}{1}{256}{} + +O problema consiste em determinar o \textbf{menor número de operações} necessárias para transformar uma string em outra. + +As operações permitidas são as seguintes: + +\begin{itemize} + \item \textbf{Inserção}: inserir um caractere em qualquer posição; + \item \textbf{Remoção}: remover um caractere de qualquer posição; + \item \textbf{Substituição}: substituir um caractere por outro. +\end{itemize} + +O objetivo é calcular o menor custo possível para converter completamente uma dada string inicial em uma string final, utilizando apenas essas operações. + +\Entrada + +A entrada consiste de duas linhas: + +\begin{itemize} + \item A primeira linha contém dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 500 \)), representando os tamanhos das strings. + \item A segunda linha contém duas strings \( s_1 \) e \( s_2 \), ambas compostas apenas por letras minúsculas e com tamanhos exatos \( n \) e \( m \), respectivamente. +\end{itemize} + +\Saida + +Imprima um único inteiro representando o \textbf{menor número de operações} necessárias para transformar \( s_1 \) em \( s_2 \). + +\ExemploEntrada +\begin{Exemplo} +\texttt{7~7} & \texttt{3}\\ +\texttt{estouro~calouro} & \\ +\rowcolor{gray!20}\texttt{11~8} & \texttt{7}\\ +\rowcolor{gray!20}\texttt{aniquilacao~intencao} & \\ +\end{Exemplo} + + + +\end{ProblemaAutor} +\end{document} diff --git a/edit-distance/input/1 b/edit-distance/input/1 new file mode 100644 index 0000000..be95135 --- /dev/null +++ b/edit-distance/input/1 @@ -0,0 +1,2 @@ +7 7 +estouro calouro diff --git a/edit-distance/input/10 b/edit-distance/input/10 new file mode 100644 index 0000000..287a072 --- /dev/null +++ b/edit-distance/input/10 @@ -0,0 +1,2 @@ +2 2 +ue cz diff --git a/edit-distance/input/100 b/edit-distance/input/100 new file mode 100644 index 0000000..4e46b54 --- /dev/null +++ b/edit-distance/input/100 @@ -0,0 +1,2 @@ +165 438 +aidcbdrjwwohsqlpvybdcwmmfzenarxclntfiqeamtededfdnepcdfihmvbbjpdmbpodsxbesrlregarwlflrxezcrfvmcubkdtzjykbsvntvoixbvrjmjreyeygiiovpxegainwrphkxnqzxlwzjekaaezrzdrsbhvde gnoaqpqxsivgekvmdujzneoniupuymqntkuvwbczxajyjxoklixtcnirbhbvhuzbvxcyhkqzfijcvgtfemouyapwsuqffnvjwqhrjmgycnvqwfqkozatfadtyflxtqjiqvrdqzomdfxbblwnvgplzkaarkiprdpfulhoqxcgegwdfguyccojpykofxkddwmgrhqbwdvcajilsuxlxhtyfaspvyukfkkbbnmkqkohfzvmegbfllellnqezamlvzvmowwguyyjfahjesctbeluidunuubjgtvzyfrsvnhmehjlergmvafqbwrcwkjmqfsaqojxjitoftaremkrurplonnxtyfvtjlnjptwuqavimxesinsvqwwwlrawqikrwyazvkoytenkmedssghxjcrrahhhuqyypmxkplynjagqmwlsrtefpclcg diff --git a/edit-distance/input/101 b/edit-distance/input/101 new file mode 100644 index 0000000..eb314d6 --- /dev/null +++ b/edit-distance/input/101 @@ -0,0 +1,2 @@ +209 327 +ujlpclzenwxvkpuzngzvhcmcxbsbeklirvyozrwsoekankrlnsgfkdzzprezjxyjakotsdnxxmxjrrgrdthsmtaiehsnrvxxtaqiaxmngknuksyayezwfonckcpbmzzeysttelawxzoxmjxnymctvkbovminoiahwuuyuplzrwbmadglvhtsiauzbmijozdhowgmmubapzgfcfkpi hwokepclxygxttsrfmmajjczmynziehckgfrkzhcbhcitofjjdomydncpayyvsnzdkjbkfjswjzvqtusauzkihtuqnrujecehvspzuklsdmhjvqgqlppwwfjrnczpdqsbscfpcpembqmrltwrpyijlzcckjzelqdzgxiimrpxedfcukgdiamjxnbunsbvbxuptvqmvxvpdltiqlaayfwzuqjrrjisnyktjmcblhffhcmecnucdlbbvljkcgxtgqokokahlevxweljjweddywlpsdgahhddghfdhbpidthmxugjxjxjaniqbzpfmbzppzmxmaqbl diff --git a/edit-distance/input/102 b/edit-distance/input/102 new file mode 100644 index 0000000..829a95a --- /dev/null +++ b/edit-distance/input/102 @@ -0,0 +1,2 @@ +58 218 +dvhvotcvczvbbofvhcxthplvvvcniimcnrosfefwybovycajiytrffxjnp isbkjyercaarjmqyztrhybxjzmparncqfoiyxacvnvzbccxspuxfnrwwagxlmgydqwkizchaydoluyfgeraiypicqfnenodykvdnncljwddlchqliwglsmnsafexckqknqrnewvxxxkdcjzvafyuvzzwrohikjmjyjsjbqabqdptmqxsusgcwjxnmsnisxrjrwxrsqhrafednqiziimxkqanch diff --git a/edit-distance/input/103 b/edit-distance/input/103 new file mode 100644 index 0000000..515f390 --- /dev/null +++ b/edit-distance/input/103 @@ -0,0 +1,2 @@ +500 500 +fdlhdwuacsywlebyictxkabcgobocfldkymvrzlitlsfrdhstcoofhklzftaofvtnisjsvhmriljfhdlaalactynvtnpngczvlutrutrrtdkpwbuxrcmiaispawhgdmiztwfkbgkaticasvfmibxgvunorvymeghlxypxvgqjeyqtpehjpxvyrmzdlyiufttztdbhowgyockfyyewoyszrdvwkzxcrzkvvmbnkdceulhzdvjegsfwzmfaywghnkuvcbdxsrmjywdqjamyzmpczisdarvssbkipvjujdzyrhzcbgsggioyscmfgxxfmyxochydrgckewtibycnxsxltkysuemlhxsxjmuzdykdvtizqnjdknlluajutqhuwcftrwkdiyxwmsvbdhmtgbezzjgoekunmrhxsdswgdiitayuewavukhaciqcbcvuadefxppelqinnosvbbosihwhpsrkgamvogwfshbuafotjbaijtzzgwx sdchnespbtrgbvyobflzacfaqugltbbaeertmtxrzsucowvwhcxxdolcenliuoczikvhxgazfwduxqgedrhkttmjtlomfhmoxmrxeanffeosdxhclhuzhfjgdvugnwyagutzmzctbqlvqdpipagteqjnyieuhnuabjxkdramnagctlbgrqhhxqgiuzwlgkkyreudsypfndrllmdhksjpobzbdbkapanixjpnjpsrdvvbdivawegyncyqlkahddssjlysxwgmjgxjncluscmbpdxsxfqpknzfkuzjhajuvqnlnuslqlyiyqblycerjgohootboanzfqdymnzdbtvmqjhcgbrtkaweaansjhotsawfrnoszpvosqfvuuswuyhturvnvejxutjsdhbzohewiqniqhzrjcdazlidhrzkiotovqpjaqbnvsmhvfmcmibnlhxaynuuiqyktqythdzosgqodwqkewoacaefjmadjgkyvvynfglj diff --git a/edit-distance/input/11 b/edit-distance/input/11 new file mode 100644 index 0000000..4041e67 --- /dev/null +++ b/edit-distance/input/11 @@ -0,0 +1,2 @@ +5 5 +civdq pnxnn diff --git a/edit-distance/input/12 b/edit-distance/input/12 new file mode 100644 index 0000000..e15933e --- /dev/null +++ b/edit-distance/input/12 @@ -0,0 +1,2 @@ +4 5 +duhz quudh diff --git a/edit-distance/input/13 b/edit-distance/input/13 new file mode 100644 index 0000000..5507957 --- /dev/null +++ b/edit-distance/input/13 @@ -0,0 +1,2 @@ +3 4 +ncw jpcm diff --git a/edit-distance/input/14 b/edit-distance/input/14 new file mode 100644 index 0000000..4c89dcc --- /dev/null +++ b/edit-distance/input/14 @@ -0,0 +1,2 @@ +3 4 +jmc bnjf diff --git a/edit-distance/input/15 b/edit-distance/input/15 new file mode 100644 index 0000000..366030e --- /dev/null +++ b/edit-distance/input/15 @@ -0,0 +1,2 @@ +4 3 +xkgj trx diff --git a/edit-distance/input/16 b/edit-distance/input/16 new file mode 100644 index 0000000..71f4256 --- /dev/null +++ b/edit-distance/input/16 @@ -0,0 +1,2 @@ +4 2 +iqqu qh diff --git a/edit-distance/input/17 b/edit-distance/input/17 new file mode 100644 index 0000000..d0f6b9f --- /dev/null +++ b/edit-distance/input/17 @@ -0,0 +1,2 @@ +4 3 +xxrx fhk diff --git a/edit-distance/input/18 b/edit-distance/input/18 new file mode 100644 index 0000000..3a696c5 --- /dev/null +++ b/edit-distance/input/18 @@ -0,0 +1,2 @@ +3 5 +unf pcoil diff --git a/edit-distance/input/19 b/edit-distance/input/19 new file mode 100644 index 0000000..e32ff8a --- /dev/null +++ b/edit-distance/input/19 @@ -0,0 +1,2 @@ +1 4 +k arve diff --git a/edit-distance/input/2 b/edit-distance/input/2 new file mode 100644 index 0000000..2a96e96 --- /dev/null +++ b/edit-distance/input/2 @@ -0,0 +1,2 @@ +11 8 +aniquilacao intencao diff --git a/edit-distance/input/20 b/edit-distance/input/20 new file mode 100644 index 0000000..f553f14 --- /dev/null +++ b/edit-distance/input/20 @@ -0,0 +1,2 @@ +1 4 +u stul diff --git a/edit-distance/input/21 b/edit-distance/input/21 new file mode 100644 index 0000000..c0ada5a --- /dev/null +++ b/edit-distance/input/21 @@ -0,0 +1,2 @@ +4 4 +lwmf nyxr diff --git a/edit-distance/input/22 b/edit-distance/input/22 new file mode 100644 index 0000000..f6b6332 --- /dev/null +++ b/edit-distance/input/22 @@ -0,0 +1,2 @@ +3 4 +wzh ewcz diff --git a/edit-distance/input/23 b/edit-distance/input/23 new file mode 100644 index 0000000..97d69e9 --- /dev/null +++ b/edit-distance/input/23 @@ -0,0 +1,2 @@ +2 1 +oz t diff --git a/edit-distance/input/24 b/edit-distance/input/24 new file mode 100644 index 0000000..df953a3 --- /dev/null +++ b/edit-distance/input/24 @@ -0,0 +1,2 @@ +3 1 +djw f diff --git a/edit-distance/input/25 b/edit-distance/input/25 new file mode 100644 index 0000000..0caa810 --- /dev/null +++ b/edit-distance/input/25 @@ -0,0 +1,2 @@ +1 3 +k jxk diff --git a/edit-distance/input/26 b/edit-distance/input/26 new file mode 100644 index 0000000..b33efd6 --- /dev/null +++ b/edit-distance/input/26 @@ -0,0 +1,2 @@ +1 5 +m swkdk diff --git a/edit-distance/input/27 b/edit-distance/input/27 new file mode 100644 index 0000000..9810dbc --- /dev/null +++ b/edit-distance/input/27 @@ -0,0 +1,2 @@ +3 5 +agw sufee diff --git a/edit-distance/input/28 b/edit-distance/input/28 new file mode 100644 index 0000000..cf9dd6e --- /dev/null +++ b/edit-distance/input/28 @@ -0,0 +1,2 @@ +2 4 +nc cepi diff --git a/edit-distance/input/29 b/edit-distance/input/29 new file mode 100644 index 0000000..9d3d86f --- /dev/null +++ b/edit-distance/input/29 @@ -0,0 +1,2 @@ +1 1 +z o diff --git a/edit-distance/input/3 b/edit-distance/input/3 new file mode 100644 index 0000000..4bedc3e --- /dev/null +++ b/edit-distance/input/3 @@ -0,0 +1,2 @@ +2 5 +bm ydiad diff --git a/edit-distance/input/30 b/edit-distance/input/30 new file mode 100644 index 0000000..785503a --- /dev/null +++ b/edit-distance/input/30 @@ -0,0 +1,2 @@ +3 4 +rzf wbqo diff --git a/edit-distance/input/31 b/edit-distance/input/31 new file mode 100644 index 0000000..dac667a --- /dev/null +++ b/edit-distance/input/31 @@ -0,0 +1,2 @@ +5 2 +drmkl za diff --git a/edit-distance/input/32 b/edit-distance/input/32 new file mode 100644 index 0000000..41c15e4 --- /dev/null +++ b/edit-distance/input/32 @@ -0,0 +1,2 @@ +2 5 +rq lalxz diff --git a/edit-distance/input/33 b/edit-distance/input/33 new file mode 100644 index 0000000..e6c97ba --- /dev/null +++ b/edit-distance/input/33 @@ -0,0 +1,2 @@ +5 4 +lkfdv xabq diff --git a/edit-distance/input/34 b/edit-distance/input/34 new file mode 100644 index 0000000..ba6c260 --- /dev/null +++ b/edit-distance/input/34 @@ -0,0 +1,2 @@ +4 2 +dscr za diff --git a/edit-distance/input/35 b/edit-distance/input/35 new file mode 100644 index 0000000..b63f9ed --- /dev/null +++ b/edit-distance/input/35 @@ -0,0 +1,2 @@ +2 1 +vv t diff --git a/edit-distance/input/36 b/edit-distance/input/36 new file mode 100644 index 0000000..cc4157c --- /dev/null +++ b/edit-distance/input/36 @@ -0,0 +1,2 @@ +1 9 +q ijdwtuyfr diff --git a/edit-distance/input/37 b/edit-distance/input/37 new file mode 100644 index 0000000..7080925 --- /dev/null +++ b/edit-distance/input/37 @@ -0,0 +1,2 @@ +17 19 +sysxlfebpolcmqspp kyunydtmwbexsngxhwv diff --git a/edit-distance/input/38 b/edit-distance/input/38 new file mode 100644 index 0000000..5f65717 --- /dev/null +++ b/edit-distance/input/38 @@ -0,0 +1,2 @@ +13 10 +ndfqjamzkptts dlrkjoyrpx diff --git a/edit-distance/input/39 b/edit-distance/input/39 new file mode 100644 index 0000000..9c32cb4 --- /dev/null +++ b/edit-distance/input/39 @@ -0,0 +1,2 @@ +6 17 +ceahgi vsjoadmkfnkswrawk diff --git a/edit-distance/input/4 b/edit-distance/input/4 new file mode 100644 index 0000000..f8c8500 --- /dev/null +++ b/edit-distance/input/4 @@ -0,0 +1,2 @@ +3 3 +oue byf diff --git a/edit-distance/input/40 b/edit-distance/input/40 new file mode 100644 index 0000000..3445cdd --- /dev/null +++ b/edit-distance/input/40 @@ -0,0 +1,2 @@ +11 3 +cmcciabzbrs zjq diff --git a/edit-distance/input/41 b/edit-distance/input/41 new file mode 100644 index 0000000..48d4369 --- /dev/null +++ b/edit-distance/input/41 @@ -0,0 +1,2 @@ +20 11 +iqydptpkcsdgcqjshznd nnrywfrnrgh diff --git a/edit-distance/input/42 b/edit-distance/input/42 new file mode 100644 index 0000000..2700aed --- /dev/null +++ b/edit-distance/input/42 @@ -0,0 +1,2 @@ +19 5 +qrxpxnlkcwdpdkswvtx wwyoo diff --git a/edit-distance/input/43 b/edit-distance/input/43 new file mode 100644 index 0000000..9ae4bb3 --- /dev/null +++ b/edit-distance/input/43 @@ -0,0 +1,2 @@ +4 20 +nexe xouyfjhnwpqfxexzxfol diff --git a/edit-distance/input/44 b/edit-distance/input/44 new file mode 100644 index 0000000..3f5cbdb --- /dev/null +++ b/edit-distance/input/44 @@ -0,0 +1,2 @@ +9 11 +blpncetyh xkbosccskxb diff --git a/edit-distance/input/45 b/edit-distance/input/45 new file mode 100644 index 0000000..5a9f9bc --- /dev/null +++ b/edit-distance/input/45 @@ -0,0 +1,2 @@ +20 20 +rosavnpxzoeoyyghbbqk utpwmhqwkvirmlfcpidl diff --git a/edit-distance/input/46 b/edit-distance/input/46 new file mode 100644 index 0000000..7709c7c --- /dev/null +++ b/edit-distance/input/46 @@ -0,0 +1,2 @@ +10 18 +kzmnttaifc nwezesomkxhaiafmvk diff --git a/edit-distance/input/47 b/edit-distance/input/47 new file mode 100644 index 0000000..8ff5a06 --- /dev/null +++ b/edit-distance/input/47 @@ -0,0 +1,2 @@ +8 12 +isyrbtul xbcjmornquma diff --git a/edit-distance/input/48 b/edit-distance/input/48 new file mode 100644 index 0000000..dbc8134 --- /dev/null +++ b/edit-distance/input/48 @@ -0,0 +1,2 @@ +14 8 +rhieqggrivouwf ghdfallc diff --git a/edit-distance/input/49 b/edit-distance/input/49 new file mode 100644 index 0000000..cd43445 --- /dev/null +++ b/edit-distance/input/49 @@ -0,0 +1,2 @@ +3 14 +ngi mvprzaeapqmilw diff --git a/edit-distance/input/5 b/edit-distance/input/5 new file mode 100644 index 0000000..23d9573 --- /dev/null +++ b/edit-distance/input/5 @@ -0,0 +1,2 @@ +2 1 +pw v diff --git a/edit-distance/input/50 b/edit-distance/input/50 new file mode 100644 index 0000000..c6ce819 --- /dev/null +++ b/edit-distance/input/50 @@ -0,0 +1,2 @@ +3 1 +gog i diff --git a/edit-distance/input/51 b/edit-distance/input/51 new file mode 100644 index 0000000..c36ce75 --- /dev/null +++ b/edit-distance/input/51 @@ -0,0 +1,2 @@ +1 12 +s qxzjztvcgvzl diff --git a/edit-distance/input/52 b/edit-distance/input/52 new file mode 100644 index 0000000..9d73f59 --- /dev/null +++ b/edit-distance/input/52 @@ -0,0 +1,2 @@ +14 9 +wnezbwxmpobmrv kwvvwquud diff --git a/edit-distance/input/53 b/edit-distance/input/53 new file mode 100644 index 0000000..5c7ae8e --- /dev/null +++ b/edit-distance/input/53 @@ -0,0 +1,2 @@ +83 149 +hmmzheqxiwhfuxavlwftgyxxhpygspvwdnvmgnwnpkdrnznzvrkmjjmwisyrdkodoafwsjfuvmeewpdwpiy hoxebjibxphiefgtsawcdivtltrshjqnkkmdtjgscnozmojnhigippjemzzzbcvoyplxenffmfdzdiojuodgbulvivhtbhayeeebiactyaovqbivudydgxwsgmhlracaayipsojleqhpygshcvxww diff --git a/edit-distance/input/54 b/edit-distance/input/54 new file mode 100644 index 0000000..c684ace --- /dev/null +++ b/edit-distance/input/54 @@ -0,0 +1,2 @@ +303 77 +blfmnqgddqpcjxzftwrlgptrkbkrlwgsnlcaudzdujbbqlfzikgxohvhtuvcjmmwvhkxcgyekjkklcjqoneppydpspiwqbkpsunedqixlsifcokfrcvrszcvdyfwuhtzptbbnxbhqjomxrbhjqxvdaserffcvkecqylqprawyquevhvuzcvfmbewpxicskpmzsbsusmaddqkwgfirlzzbczeghmuhxnxejrspcvqejwowqsfhovhctwnhuuveprriyfwstsjdecyyfjbjsdlegqlklxiyrwvlppomdfdtvtkwok pejxibdknponpsxrytoqgjrtjpatmdlhmqegvjhvlehsykrlvvssmambzusxuszyybdrdvzdbexsg diff --git a/edit-distance/input/55 b/edit-distance/input/55 new file mode 100644 index 0000000..bf6bc24 --- /dev/null +++ b/edit-distance/input/55 @@ -0,0 +1,2 @@ +185 178 +kvmykifwgfncsacjlkathfmnlctsqejfoxyvmtottlhrlypbzisucllqgaaitmxpmfinsowjaawsnmluizvpjbewqcipcqwvsqfbeutdcsdrviozobdytwsimseetqcklnkxtawoxiysvzrakqeispnddxtnfqalswxsmksfooiwxynamdjxnsmki wdpzjpkibcbbmzbiwpmjczcehtczqjzlkgyvszpuuvetdfluuhxpeopuxmdylaysttenjmcedcumoeeicjtxkkvxcxjowrcvlttsqhwkbbmigtqlovjgviyzgcqjvpvotwucsetidicyhtcmajphxyyooeovuxvuploklpbovqdwdypbxg diff --git a/edit-distance/input/56 b/edit-distance/input/56 new file mode 100644 index 0000000..3360323 --- /dev/null +++ b/edit-distance/input/56 @@ -0,0 +1,2 @@ +251 5 +qwadgeedjkgurhsxdvylmyfjqlwzldrouylqobsgemwdoibqvcyedfvqopfhkqmhusxqacoogjxcoxbfzlwcxfvqaavfegkcirqqgdyhljmaqzqifuaoubukypavebvdujgsulahkprfpnzqaqgvfdxwtqflceilpmszizfwbonxplcyqittpkpbcfsesgfbiqnipolefrelphjthqrzsphbnumgrifmwiztfuhqibgaxdvysyvgxlspmin yumep diff --git a/edit-distance/input/57 b/edit-distance/input/57 new file mode 100644 index 0000000..4639cfa --- /dev/null +++ b/edit-distance/input/57 @@ -0,0 +1,2 @@ +431 27 +xuoavyovdbielzdobgqcjznjbexalkghywioxzbvxzfcshcozmefwcrvyibjdfqvqmhxdpccjodlgvkplrfdedpzoprfeechwszhvcdooejlchcwcektfrdmowhsueavbrawmihzsnfhrafbqeawdixznppfwieaivtmpqzqtsvnvwjmgvhuesssaxgmoywdgvwiouzuqdebijcqycftaftuwtgxavemciuqmxenprpmyzrexshnvtesstwhytmatxbuzxpstpygfxphpfckjdbfbximeeswyndfhomcnwjtfruvzwbhlzbvebyeucepgcdpmghcibfxgrvnacxwlopxsvzclwymwdmoljtaguwuvhxifdjqshlqaueglqrbxuwpozfvegdpvnwmedxbmxagimxmxgjlnnfkwbrqshxfcan flqejafdktnlpgvlexcyglrzbkh diff --git a/edit-distance/input/58 b/edit-distance/input/58 new file mode 100644 index 0000000..8383dcc --- /dev/null +++ b/edit-distance/input/58 @@ -0,0 +1,2 @@ +182 145 +vuobyxcxzxqmlswvlmbvcsdtefcqtmlilwztbscfhjtcytonmliivrkbblvnmhiprgeryrpjpjykchneyfymiefymajrnwjslytbxmduwtfzafkxyfmcnljsebzleygeguujmkyylfmmvviljwgcyhrdldkzfzgtvmowlbeqtjsodvhbuumexp xqhceqldfavgqlvituzzngjeotbkjzcrtggluiamncorbkiwdozitqgqiphvwuijwhsmgogxomluqurcwogghhjjcekggllamqgxhcfcmrakgrojgxizwxascasinzxcdxewculofitylhxhz diff --git a/edit-distance/input/59 b/edit-distance/input/59 new file mode 100644 index 0000000..0a2d658 --- /dev/null +++ b/edit-distance/input/59 @@ -0,0 +1,2 @@ +397 500 +dlisupdylshahcipzoptullyisxsczjqawagnngcggiwkhnarjisvcdpzggtlludvcsjxeubfgyjdimtpftgytkfntylnflbfutsyovxmligoaiqzlxwfrsljucdxssamgcifdljashcjjwhlkqnipxzjglptedzxmthvzgruhhckufdecakrrzoqfqcduzhjsdaskqglqlnnbkuuytqthfcjraawtbccurpzpumcsmqhebhqrfigamblzxycvevluzcuqxvrjgekyaofvrvcohldavkjiykhccmnjpdhkkimpsmvcyqxlgwlbhldkjlzwthkfnizebvlgozrnwwvxdckgnckqtkqidhoociwrpkxesldtgxtaurglbgmpyqlpzbnsbzhanbi ziqurwrbrbxmhbrdpdrerbobajuldlwrpkrtfblspnkxyitiohlpgjlcktlaqsalnoiphbtuyrrghseznkmzukaiihatzttiylactadtninwcsufbynjkxaajnagfevscfuhoajuqmisgbbsxqbylmraszacpliuglqyuzbnizxxjxnntsckjzjzjmmyfmvxjaopvefhwhbyoapkqedyddtrpblporursknpbtamzkkzrrddcmrayglnjuikqynjaucaqekhcwxdqpdohycvaexjyulgvwtovqgsfivkvunqdekhngxjyycspvzulhkywgqjgaqclpsxnserdnrjxrozmxtjtvossyqpvotkhmbqaxiqxuxzlztksohujrtaimpdesfqjbjifgybebnuiicfjteqfvsyrwwjzissaimgcusleiacqxjipdtiljqrbldlirsiewjplnaidvvixjqtqjdozldbbeemvmveqlhjztcouost diff --git a/edit-distance/input/6 b/edit-distance/input/6 new file mode 100644 index 0000000..f33094c --- /dev/null +++ b/edit-distance/input/6 @@ -0,0 +1,2 @@ +2 4 +nu yndm diff --git a/edit-distance/input/60 b/edit-distance/input/60 new file mode 100644 index 0000000..07fb2d6 --- /dev/null +++ b/edit-distance/input/60 @@ -0,0 +1,2 @@ +297 58 +omekrinqbgvgljhveaonqkrtjjtlgbkrnyoixirslfszfqivgkaflgkctvbvksipwomqxlyqxhlbceuhbjbfnhofcgpgwdseffycthmlpcqejgskwjkbkbbmifnurnwyhevsoqzmtvzgfiqajfrgyuzxnrtxectcnlyoisbglpdbjbslxlpoymrcxmdtqhcnlvtqdwftuzgbdxsyscwbrguostbelnvtaqdmkmihmoxqtqlxvlsssisvqvvzotoyqryuyqwoknnqcqggysrqpkrccvyhxsjmhoqoyocwc larjoyiqrmmpmueqbsbljddwrumauczfziodpudheexalbwpiypmdjlmwt diff --git a/edit-distance/input/61 b/edit-distance/input/61 new file mode 100644 index 0000000..076b14d --- /dev/null +++ b/edit-distance/input/61 @@ -0,0 +1,2 @@ +447 161 +zhpxneofhqzjdmurgvmrwdotuwyknlrbvuvtnhiouvqitgyfgfieonbaapyhwpcrmehxcpkijzfiayfvoxkpasyiwxmrahuwlaoovrejhpbiiqmdptefnngfztqhhifmthlxkqbhisdxbgotyspnvusldlfcnogndbcjxqdussoegpwprfussjqhkhbhphtjkywsebaavjaupvdbxfitsyojevycpxwyxfkzdesbnoacixwtrhqhfimukkdinhwyxnjkmopbhoplfmplqjyfiazkxxdmzbnduoaxjdaevibeqacbdxwrgsfvplkhfpnlpflzndtluwrigjjtthzhpowrylzzyvnatbawwxbyduusbdhbggawqvlrbmpgknzvlkeeaveklvqutzzdrqonowwvwjfxxltxmxkkpzkyfzsvyvkvnycvpnpqbribpem fpniwazhbjezmenvessyppasifgssfwveuxasvkmpxzvzooptvozcyqpxanftsvgluxxmwtertadxmamtxrdqnploagmmgethvbnexecqidnzpszhlhpsoemjfrdpfawnfhyquwiwnuqztlhklubmjmqimoyumbup diff --git a/edit-distance/input/62 b/edit-distance/input/62 new file mode 100644 index 0000000..f3411ca --- /dev/null +++ b/edit-distance/input/62 @@ -0,0 +1,2 @@ +338 358 +zzxvkjjoxhyusuklaiympopzyvewmvqmsoisxzuhsqazgggnmruxdkvgpucmtzosjlrpdwaekoxtrawmhijizuqrlnkieylaiiymtdftxjuucjipozzhgbizwmncrcabvmqwafvmuxyybvciurgyaptmpvlcnyuhaytabvkspwisdsdspxysopdemqdgqaxuooompkysokvzzhdpmvnurnaulfutcukwgtxnqxmukbxnlidvysewbwmsnsrfpxxftmjuedksdmnbklsrnjpwvpqwmxxtffgtbdbjifnrvwztbdjrbazxotgfqvyqpgrdojjgjvqiwldvjinoee jcisyvutvhvmiycoyszfexxafmkaxsxwktfcfailjabwunylerksnhsaqnhovlthjvsumbzqsjhrllovoyubxmxbyunvaadrvbejoorbyhwunrhnixrhwodlxngpqurfpiqdfteswnrnyfnrlltctmjvsjxpfqsgpzeqqtrewwsceiceanfvodtiokdwtzoqoboiioxgomodfaszwzguzzyqitddcinemypcbfelhmhypbtbwmchqhygftvaofpxwmpmfbcfnclqexjgvzpqbxcqoskjdxwhimeuwxopzafascsxawaroblpmamklrwlznplgspuzvnubpudibptdslaagxaaacqrsfvhc diff --git a/edit-distance/input/63 b/edit-distance/input/63 new file mode 100644 index 0000000..5f78a32 --- /dev/null +++ b/edit-distance/input/63 @@ -0,0 +1,2 @@ +166 250 +dsmlkjaqsoqgfpovigxfvhltpwptojsardozogrltulberiywireebjddkdhpyleypylevvglkckubmygxzqmeeyehjehknbkprsvdgjoizzgjszebtaqqgzwyfgdcbkdgxzurjpoahrhdpqexzsrpgvdutabogkwkuehf vamsntzuvcrqzplxhykiaoapjzkznmlsnezsskdlosiyfawaznbuwenovcsfkfuhntglvesxsrrnzkbhzkhzmvkjevsrbdiclckmsgpgngyckzvgysvwcgwayjokqactfxtivfbdwprufivtggzhbpvlxfkisdneogdseenjlewrobjhpppjczyxeaiqanaztksnpfwyhdjvipgwzznmnnxwraiieicscdhryzvrhtoprratxufcithoki diff --git a/edit-distance/input/64 b/edit-distance/input/64 new file mode 100644 index 0000000..e656fcd --- /dev/null +++ b/edit-distance/input/64 @@ -0,0 +1,2 @@ +434 142 +dggzpvjctbahnzdwtokiatsriqzwedrrfzbrkgvynbbfomoiawwmmjiqvhdlnsvwnwbktehykevhacvdflmnkrljmijvfxdvdydmvkjsbpmcgmnftseumhbdiohzcjvpayxqwdpychqctudlkedtbjduqbzwxvoxjlajstaoqnrrrpxcndmwhlwdygnnordxmujnzlkeamdxanokvbvplrwxzijpjkulodeuluepkslyiuzywpyyfocicazyewqyuljlfmthlieolxuypkqpemfjjpswulkngytffixvoiyuusybdmygpugzhuerhlfelemnnavefsuqiknyedqtxyekpwpdpcuuimosytaspbminxpvbcbqolosvbrppgpyvixlsxhqdrphmjpiherrwhdwosapjftergjszlzwcihwcuegfc qjnnffmvveuptmnefbhohjbcaocdwjyaylnvzeciuclquqednwkyfymgrfmzxqpejcixxppqgvuawutgrmezjkteofjbnrvzzkvjtacfxjjokisavsgrslryxfqgrmdsqwptajbqzvethu diff --git a/edit-distance/input/65 b/edit-distance/input/65 new file mode 100644 index 0000000..ec9c62a --- /dev/null +++ b/edit-distance/input/65 @@ -0,0 +1,2 @@ +303 468 +datxghfzqrwvfgakwmoawlzqjypmhllbbuuhbpriqsnibywlgjlxowyzagrfnqafvcqwktkcjwejevzbnxhsfmwojshcdypnvbuhhuzqmgovmvgwiizatoxgblyudipahfbkewmuneoqhjmbpdtwnznblwvtjrniwlbyblhppndspojrouffazpoxtqdfpjuhitvijrohavpqatofxwmksvjcvhdecxwwmosqiczjpkfafqlboxosnjgzgdraehzdltthemeusxhiiimrdrugabnxwsygsktkcslhjebfexucsy rptebkjhefsvfrmcqqdlanbetrgzwylizmrystvpgrkhlicfadcogtnigdrxaslquolbtomefrtocgsyyxmmsoessjmkvhskploeetlfvcjlilcemzwtvjilgdvbvafaeqqojypxjdyxdzxbtkccesympaxxhzcaqjdoixjiivinpidpfjhvavbwpckqncjwygbbdwbqjvdehkevsntanowlersappruokywnegncmjvjxcsalrmiuszjmkapbwdvdnjxnxrnlmirlmehsayuhjpajkuxsyrirkpmgzcyupoigwsdqsuxmaixwsqgvlrjzfcqrphsbgrsfneaijelhyrumkqpkqklsacnhpznpxzsfgmcoubkpcwzmkmaxjypvswrigsvqgogoqcivazsindehaozddwxttffshovpvpoldlonlkeggvxcyqkabpwnrzejfdopdhxkoqspev diff --git a/edit-distance/input/66 b/edit-distance/input/66 new file mode 100644 index 0000000..9f15038 --- /dev/null +++ b/edit-distance/input/66 @@ -0,0 +1,2 @@ +259 100 +eochbdfqbvcoyvffvzauufrrohjtxnjzpmkdkjbfqflivigiwztgbybugifdyhojtjkoaqiehkjmatgyhgkjumwvalsqmcoiijvwchnenikrlizwkhktdxtqvxibctbnbxfudivicnljlnzpghkvjcosvfnryipiiylotxanmkcljvyycmrtscndzivghxaigwxskrksqjokvncectsfxpgyorkufsaaciqgncvxtghwtpbnfskrmpzcymxugwjdilc rzpuewahxylcgnzksusrauptymacgtstkdxwygkdrggmqkomlrwrroqfnzpvwocuaggxcvbflauqxqbwtfyhpeyfdpydbfancnkg diff --git a/edit-distance/input/67 b/edit-distance/input/67 new file mode 100644 index 0000000..9819176 --- /dev/null +++ b/edit-distance/input/67 @@ -0,0 +1,2 @@ +34 188 +myhdodvbiqneqfwsvyfrpijygjduhwaggc dphkrwyjcqgzpsrlcjuybmgaorppyffunuonatqseysoubmiafjbzxuiwszuovqewcolejflivckbbwdjgmzvfkxzxfdcxbaymmntielkjnzkoddcpfepdqhgyrawgymamljwnbieawiufaepocjmcsoynmiuplaekaxexiyjfhhgxeqpxsvievrooop diff --git a/edit-distance/input/68 b/edit-distance/input/68 new file mode 100644 index 0000000..5fdfb6f --- /dev/null +++ b/edit-distance/input/68 @@ -0,0 +1,2 @@ +317 122 +vxqazpxldlyeqwduiqurnwsmxxarzoampoqoxcmqgamihmsrjnrlnijtnzxcdyczmyfruwsfkvxvljuporlhzeqqzrlydqlxtgjmxdstcrabjcopybqybaalilyzhysadroqijfhyvgzufdlrzgecmeqtgkfgifpyiehmcgrpopmozmaecxfpkwzeualgfdmdexmksipymegeruxgtganeljamwvtxfqfcehncnhxayvdrkwppxiscaykvmkyjkjjgzidbatjujgdcsoqnlxgxxdeyewhvtncvpusjinbrrjcwfxcafbxpytbeypc mpdcbdcmjsfzyoohdzyudjoukiowfcmhpliccyhiigrnjmxyafnxnfzvnbnsxbkampswfmooflqwwdnsajuzisgrzozdgnhhuaibgyctpyqhcxchhygihqaerm diff --git a/edit-distance/input/69 b/edit-distance/input/69 new file mode 100644 index 0000000..914987b --- /dev/null +++ b/edit-distance/input/69 @@ -0,0 +1,2 @@ +416 308 +gomqkyltmrfgqbdhiloyxfityhewgmvcakcxunuxogdvurumqogwljlfhysyjvvefpkbyibzeqfjhzymhdkdzueqdhnyvqtunonrxjnfbrukwlfitfmovpqnrohznpyfcozugjybluvniqukmswcwsriwfqnhotbayaeqvyphrkwutqicjowqmqneitncvuazznjojvltijkfxgmuuxqaypftsrhsifdbppevhqedzpwomzrsdejwfsuuxewaumeynnlqrknkotncfknvzsgbkeecuvnqpefkgbidlrskwxiocwgraidgdledutxclalkbnjnwmgsbotnpgrvzqrgjkwpkadhcsccxycukreswgwzyjorwcbokbmkpftucrejbrlpnqhmccqjnyvegkvpeatdzwcwabg kkdyfgubjdfdjnilummwxgvhhcfgrzinrodtidtvluobawqmxeamumkscvlhmivfubjcmblwkoxskirgqgnilltztieaipfrrshtqlhxxibaqmqhmbkaimrkzvgewnjpevfqgywzppbieigzkkmpplsywcofxblcyjvesuhovqvuygolnpqfpyrwyiubiwqjdjhvjnttzfnjimryvpyhoflqtfrrtldujwpinxmjmcmwzmdluubvwspacmhcwandvpqyiqtozipddjlatrprdnygmbaynlfzmbmtrytsqsxsuejlgooq diff --git a/edit-distance/input/7 b/edit-distance/input/7 new file mode 100644 index 0000000..4001be6 --- /dev/null +++ b/edit-distance/input/7 @@ -0,0 +1,2 @@ +1 1 +v b diff --git a/edit-distance/input/70 b/edit-distance/input/70 new file mode 100644 index 0000000..5475b77 --- /dev/null +++ b/edit-distance/input/70 @@ -0,0 +1,2 @@ +453 117 +cqvjfsmhxmhxbcbdqskznxnnphsoqjfmaqklcmckfgieszpirgotzgvlhinlogmtfnrqnxobylzddfyfpytcdezitduqhozqxqxxtxgpzkkbxmkuhdomjnrftojtrfyupnvuojdbuyczoahwvuuvvzapunxuypbqqxryahdfhfrjsxyukjfmruwpjajjcvjbkxptgqcyxdcvaajmdhkbaaxqvzigybwniufucucbztnisvhqszvktilnagluptrwdgtcdzjjxcnwesqxffbxyuqmqvydzsruhxevqymjurmjnilnrkeepdsyysvbaeksozxfnzxewjrvcboxljnxjdxgfhtgrdxohnjtiynspkwgtnxsxjrijytxlcasqpdljzlnxvpsbjqekrunuehmhngyumgjhboeobqnlifeskivabbaeputxuurwpowhfusacejx sqbomleugdhzlvtzvjkzpfzyczivpioarkaxawrpxyzosglxxlpwnwnlzfjdldrffudmywwpjtlkxmoirwvolekxpmyhdyjaeqwknfpapuegircdowkus diff --git a/edit-distance/input/71 b/edit-distance/input/71 new file mode 100644 index 0000000..117a91c --- /dev/null +++ b/edit-distance/input/71 @@ -0,0 +1,2 @@ +445 340 +nbrcwscmlugzfkovxysypzekeedcemnkihrylizmakzwcdhqdxfkrvsqfhcliubnuwcjkdgpoynppagpzhmmovfuradzempdwjfvvtgmsalswwbvjahwerctoezqyyzosxhijgkzkspppvvljvedhurqyxrlhtezgphnbpuhgkmrclivkhnztoxsejnoepwpajuqrwzxnowqxqpjbxzsybtyafrqtleckzuxdlwouwijcghhgnsowijqphemojmzaieorvnbnswiuuyytmutivrdupcguvsgngmqwwskxgldlvdrmmaqhczctldsryaygnndfgjgnualnzrulirvgrhhpsozmstvdjcsmaachwigjscnapsumxpzlllvjjfoamemxuutilacvkeccfezywbftnbwyjtybgrjtqckytlhdzzuwqkcgesmfucyq qxsjrjsnfuwbdcdqsajdimlrcvtjcxoettgxxjjbcnwunuuyeruotkwxkxctoveunecfrcwvytiytuiwsvwqwpijiskvoqgyeyorjhdskbcatyupyqpbxpvtltudzmivflmfcerjopfqfwtjcyazcgrmfdlvlbaxdnnbxtaosqrgjernppfrmaxzjqcpqmqhmsiruqeuxxvevdtkbghfvpnipvglddrrzqwohcpyakjcxkbopxmxjkiawlyibcdhbxeunrsvhwsveyywawnfpjkpbcpssadrkyqvsjrqbyebebcbaaejcjnoyvyrcjunqyagazpglnzyrzwmounb diff --git a/edit-distance/input/72 b/edit-distance/input/72 new file mode 100644 index 0000000..6cebf0f --- /dev/null +++ b/edit-distance/input/72 @@ -0,0 +1,2 @@ +82 234 +rlfalqdkmivhixjqodzcmcguqqyxtnouaryqcmaeidiqvrduelohdqbagtnmiweugtlgugdbgxrikewsvu bmotaoocrefbnblevntpelpjkuoyhwqjjrivbqwzvuzwoubmqbombbgqbfxhwhiybfkvurxxgkonddforjojtuttnsdrlicjrqssaapowjzuifxqmsvxqjnnoxijpwcmhgcbigwdadearleayzochoceggmopmxqszwgevpgjisnxeprdyqqdffioaglkbvxvmqobeaxnfverarxqlptsvrnetghetglskmdxuvooc diff --git a/edit-distance/input/73 b/edit-distance/input/73 new file mode 100644 index 0000000..0f28096 --- /dev/null +++ b/edit-distance/input/73 @@ -0,0 +1,2 @@ +428 394 +ldyktwujxbbuvlnfbdcfcxdvgxvbvlxcqkcodataeuhvsklcgcwhsjwwgazczvznyzrvhxetfzzawpkyigzatnxiavevwfjuonoqdskgsndfxrpdsngzofadteizsbibrrvubfankrbkpxnjxqpijmksnjrtyfltreyenpgsaitrjdleypotimvwoxnvojzxbbntnumomgzlijhafvzrodtnwetxetdnxqqrnnngqitrtfqtuvmhudfeuqpwctkvqauteazsjucfgplkpgezvdhwvuzkbhbidbtnshgwpfslnwjgpbptaqylibhzfywzuszpacxukbzwopdrktpywoirjwfekxonwbykstqukzajlujjuleqoruftafgnkiskxktsassjrrwpocegowqksbszlsvsygalcpesntldjgr qzngiqynifowbgctqvazpkuulwuzyimdlsgkonxbyytntzkxftijjrwcrsekwatroturzpnosldlwpboggnjcwtfopdhqgllwxrydxernsfecyjixgwveticatgaijqizlkgvhlhwsglhegziyuoeqdokcgbqfvbrnhhsbepdykkyygeutuifljazbcnxisfcodiqojdengxjqflodzvneenrglavzynyhsxrgdiqpnusncpydzjqktyelpgmsbklvmnlpgxcienkrbjuwcmllbkprlufjljokynppxbkyisxmmanlxuyeidfzvefwwcdkrpiiutrwminfzxgetxttsigfkgofekpiuwyzflpklbimtofjpxqkdqyaoiwlwmjakzvhicdm diff --git a/edit-distance/input/74 b/edit-distance/input/74 new file mode 100644 index 0000000..d68e209 --- /dev/null +++ b/edit-distance/input/74 @@ -0,0 +1,2 @@ +456 339 +xgeryppfgvhepimgrqolqyibjphsjkmdkaqbkywtbqehrmybevnqutdlyqpogemuudzxbhjlbgvdnzunubuepbcsjbpcydehbrgjppiqebgxhdtqxwizichytscewaoudjzevuodgdgqfdzvrboxopvfdboyskolrvdfoirkqpiwowgypybchbmwtbeaolsrxqcoxwntbyimajfpauymwjwibotkziuttjqcnhudhylqbxrbxkvmudthutqqenfncshtaqswmqucjvuzcetvnqqjssebslricsvmwqakezgiryrhlxpeugvsbipcsmymhulykriyhdmasfcjuigrwjchmjslmpynewnzpphmudzcbxzdexjuhktdtcoibzvevsmwaxakrtdfoivkvoooypyemiidadquqepxwqkesdnakxkbzrcjkgvwwxtqxvfpxcwitljy dgsjytmekimkkndjvnzqtjykiymkmdzpwakxdtkzcqcatlevppgfhyykgmipuodjrnfjzhcmjdbzvhywprbwdcfxiffpzbjbmbyijkqnosslqbfvvicxvoeuzruraetglthgourzhfpnubzvblfzmmbgepjjyshchthulxarzhizeioepwbizhzkbdluytbvwvqipizqcwcajkufnqhmcrmmxzbljplvpxjgexdfzllnnbugbmcthspxenwovywdfchidwcstlbocfzzyocnmgaaujtrlqsniflvehwyippbxhvuifujifkwltvjbkgqpooptxemxkrxoihboky diff --git a/edit-distance/input/75 b/edit-distance/input/75 new file mode 100644 index 0000000..1ed21fb --- /dev/null +++ b/edit-distance/input/75 @@ -0,0 +1,2 @@ +318 232 +zinrxtbraxnmhkcsshguuatppfhdhnwpzukjybkkvrmmpueehkjyrcrkpkhtbfqpyvrcfqalhoikwfsqfstyfpraahxhjxvsscngggkgnhwhepguyavzcfdkqbcmgroidxrzyynhwcdiusriqsaowczwuuyelcxepxlwdcknmdxautbdnrahitqisznxnisyoorkepoprzklkgkhespplqssaimtlltgafhvlcciztdidxpwhdghoscigpptaurarueihxoootzelvqbhvoqiozhstfxpwbfmglkickrgwolhoakatssjlitqzjfhd mdadkyprfjsitgvqaiofzwnkpryckxsjozuinkhufnwhjcyanirdgwlfwujgzcfgrlnkvyfopqztsuqshdtkdgbrrkxwqpglipcaasjhklypyuurvgzbfagbnqjwksdmgdpfkdgqygsemvfitdeilcydjnhupzveasvkjxgamxntqfznqkmsoareinwjeikyorrozgfzhoyhmkupvgurwslcqszrmoaorluildoy diff --git a/edit-distance/input/76 b/edit-distance/input/76 new file mode 100644 index 0000000..149e629 --- /dev/null +++ b/edit-distance/input/76 @@ -0,0 +1,2 @@ +88 326 +xoyqzhcbrgifoqrgxbycqooqdzmltuwiqgfuldupxavnnjtrelaqikmvgrpyshcstahtzdbrvchptoadvzuaikcs aroqjnjhmjcumbxgszktqfruostvevhhheciomzzkffnhmlkyetbkvnvdoimakkollyunrcnqudgazmejgoahkjafilhxvqyssvatigcjzxibtiritdildtfggbyzobbmxtwdajawqdywnppflkkmtxzjvxopqvliwdwhzepcuiwelhbuotlkvesexnwkytonfrpqcxzzqzdvsmbsjcxxeugavekozfjlolrtqgwzqxsfgrnvrgfrqpixhsskbpzghndesvwptpvvkasfalzsetopervpwzmkgpcexqnvtnoulprwnowmsorscecvvvrjfwumc diff --git a/edit-distance/input/77 b/edit-distance/input/77 new file mode 100644 index 0000000..3433db3 --- /dev/null +++ b/edit-distance/input/77 @@ -0,0 +1,2 @@ +118 223 +rounqsgdruxttvtmrkivtxauhosokdiahsyrftzsgvgyveqwkzhqstbgywrvmsgfcfyuxpphvmyydzpohgdicoxbtjnsbyhoidnkrialowvlvmjpxcfeyg hmbcjkupojsmmuqlydixbaluwezvnfasjfxilbyllwyipsmovdzosuwotcxerzcfuvxprtziseshjfcosalyqglpotxvxaanpocypsiyazsejjoximnbvqucftuvdksaxutvjeunodbipsumlaymjnzljurefjgutaqnromymikefrfroxcsxrkxpictxgvlernyteflncijhmlislunmaosomksnmt diff --git a/edit-distance/input/78 b/edit-distance/input/78 new file mode 100644 index 0000000..f922132 --- /dev/null +++ b/edit-distance/input/78 @@ -0,0 +1,2 @@ +434 355 +lzqlxddzbfftumvxltydlonvaocdezwtpjozmowkqwcvftejhxutnhjrgwsnbytsgtigomkngtmnayttzncqdewyzxwsoieshpdawcrzhbllhlxlixgihzteyfaxzicqwhablkkhclxhfoqbpcxwxpbvpawlnfnatofekrbxsfgejtcdqkzeujunfcuwevyajbjaruprxsykonesfurjqfgbxhtymdqqicwecdlcsrewziynzuwndnatnswigtqwmplhtcqlcxsunzwyaczgwvuemazdgdrcfpxnlvdzvauuzvtxahlrxdbzzgorugjvmxeugmycubktumwgrrwqilyubvjibghogaznubgqseyswunvewtcrhnikgegliyjiczsekymtqzthxqcehsezbhkufqgmgrogewpmrxlqwninogkyz rleglhrkafljakmkuydglamguxucrwsycuuoivhywyicdquzghgcysdxmfadgfywrjjsqmycsdxprnurizkjvvrhpmcmodfsejoeetzkkjftddmysvxjxcttlzsrqkrcuhliumyxzxmpkvfhtgtuiripaqwzkcebktaeuijbtanrftvkpnrnxcmfumotrnenqiwsvgjobtbkhkatmitbnxtnsklvilzixlgmufflrqgftanexecptwygahzicxttrjwiyklirghyqmlwyjdavexjhvzhrlpkwfhsqzprgircvvshsdmqycwhjzanihpdsvmwvjqtslqelnwxtoqfvivirniaktvzbmv diff --git a/edit-distance/input/79 b/edit-distance/input/79 new file mode 100644 index 0000000..b5f1cc8 --- /dev/null +++ b/edit-distance/input/79 @@ -0,0 +1,2 @@ +26 111 +huacgvbgshvkwgvrkedngmadoc upwsspbchwlgfmueyturfhbhzduaymbawlrfjdfhmmocrouswmpyxfpxwwyxykjuvoctgkzziiunytvxhkjrfdsqntsjudlmxjlkwiaqeojuefc diff --git a/edit-distance/input/8 b/edit-distance/input/8 new file mode 100644 index 0000000..a17816b --- /dev/null +++ b/edit-distance/input/8 @@ -0,0 +1,2 @@ +3 5 +tsz flegs diff --git a/edit-distance/input/80 b/edit-distance/input/80 new file mode 100644 index 0000000..bde4435 --- /dev/null +++ b/edit-distance/input/80 @@ -0,0 +1,2 @@ +175 497 +jyixmzsmhqqjoteodiatbbsrvbbvlthddpqfcyqryuugbsdgniaxthihcysjbouqncpflccyqkbuvjljijlusunvfitiwicvfybjyqpgtqnkrmwunvimjrwftnqmokixfhapmsicyykypujlmazxnhktapnnnplrslnhthtnffdpewd yyaawyehrwdtrukbwnivyruxiyvwppjelsntognkrphqlbtmzpgpkdgehpbhusfvsbyixflkozbxyavqpiauovpvbvlqgxlvueenvzxzmrknugdzkixapemdorznlxbwwfridaluerxucgdhhajziciwovoisboxgxpxmftrdvduttjnqrfczeawafeqxhnbziragcrrjhbhfzvkzdmufczeybrskgbcibxmsjrbafltbalkobvxhinlqbnsrmnwwkqqxdwgxvqwkxwzhwngzhxrirwhhczpnxmwqrochdzfiwzqxaimcojsrvdxxfkkhyognkrjxbljmbsbzbdrhczlvpoyeqaywlpyxaflehnvhykqtfnzcopcqremmbntrqdmtiwqtcphenxfninboegxjgopifnpbdxcrvjldzavdpaedmyqooklctyzfpqnxiqfcyaoouxvripjxpmwurmhnidhtqdbnjxbtrdqisxyxmnpo diff --git a/edit-distance/input/81 b/edit-distance/input/81 new file mode 100644 index 0000000..573ebc2 --- /dev/null +++ b/edit-distance/input/81 @@ -0,0 +1,2 @@ +198 471 +vodnvuhkpvgzkqfhyaqjwfzhbozkocbyomkzchqlcnnzdqakmytfmntdgojcgnejhpmfqftuuhgpidpoiemphzcultdriaugjezaerrdgkjfuawawhyivlkeqruoititprqjytazbpdryfvvtsnewstrwruectttptzaaasnfdkpntsdkdrzimvlmhzlmohgukgwjo xwbtijqksnwlteqyyxqkbxsvfnjzttdqmpzinbdgayllxpfrpopwciejjjzadguurnnhvixgueukugkkjyghxknedojvmdrskswiotgatsajowionuiumuhyggjuoympuxyfahwftwufvocdguxmxabbxnfviscxtilzzauizsgugwcqtbqgoosefhkumhodwpgolfdkbuiwlzjydonwbgyzzrjwxnceltqgqelrrljmzdbftmaogiuosaqhngmdzxzlmyrwefzhqawmkdckfnyyjgdjgadtfjvrkdwysqofcgyqrnyzutycvspzbjmmesobvhshtqlrytztyieknnkporrbcmlopgtknlmsstzkigreqwgsvagmvbrvwypoxttmzzsgmycvdbkoxbnlqrsjebzaczqhfycbglsgiveaufgdatppvtxheypgezfqyvifacqsdaixdvpktalegiy diff --git a/edit-distance/input/82 b/edit-distance/input/82 new file mode 100644 index 0000000..a3d273d --- /dev/null +++ b/edit-distance/input/82 @@ -0,0 +1,2 @@ +32 369 +mzctvkvpgmazegbvsaugicbnlbatbtmr lcfnxvvsmcjsipcjxzjcyhodprnopallydgtbpqcrhfzrjxsedimvmjclpeqopkudapprsrquuqayaxdksyshndaguszpptcqzvauezgelwtyxfsexvbmmqpmhlccibmwzlcaaismkybrfpzhhwachyvszpchusetjrcnxnqgrbivwxoqiykbtuihlcsmeamndomdrigaeyvvmsirbmuregskdefongmuujhispctzrydyesxcczehoakzzojtqzwdldulnqvzdlqwzshevtamrnwlbsmmgbmmqfufbcfmtxufojqjaywlxjifuhmpfhcwjbkkiwohvolvrdjspzgzyaztmoayznlxhwwgzmargobaalr diff --git a/edit-distance/input/83 b/edit-distance/input/83 new file mode 100644 index 0000000..99402c5 --- /dev/null +++ b/edit-distance/input/83 @@ -0,0 +1,2 @@ +439 23 +eaiimetfdacucmcfivfxwazmtblfuzvkqdeetsnnrcfuomfzoefjvvrpzqpazatfehaisqcgjnqvugbphgzpevepumugtfgyfmytepeppgjpmjobzvjzmiygysgtkuhrtknflhoqtapejijbsfekosrhhqclwomxipphipucvoygesvoqmeejcyceomqmwknogjducenetovmezanhejlhlnlcoeebwaaqnbwkbaaqiryinndbufprshsvhfbvpdafftgbkshhaqaeziduinukosxkvzsufnxbrhpwcqvvouhzxbvqtuczkbujwyzdhvugdvpzlzqtapqpcbdazbitbkvcjhhhecznadknedjatnarmibhuzkgduatemmzexkhinitqmiehzegtoznmaivbtuznmijltycazmxxtmdopiqiuigcgqzk crmhmlzqszuuqiglrgjgwuo diff --git a/edit-distance/input/84 b/edit-distance/input/84 new file mode 100644 index 0000000..efaedfa --- /dev/null +++ b/edit-distance/input/84 @@ -0,0 +1,2 @@ +190 41 +ggoapnsszenvzwsgoiwbrkiquumqzwyyndkyhgutfbwyqjvcxmxtwdfwcgjxfpbszcbbuctdrypicjtwsnaoxgdgwrvqehdvnfccqrzhenoereogljuxvwagqoaddbuauytqumjhfzquiwypekvgsjuadahsijidbnrqkjuznnlxjsknxdgosrsffxtoxh ekfanivtnbcedwnjzodbbccudvnegdosulvxiznxu diff --git a/edit-distance/input/85 b/edit-distance/input/85 new file mode 100644 index 0000000..a53f0cb --- /dev/null +++ b/edit-distance/input/85 @@ -0,0 +1,2 @@ +289 371 +leotaisnrcvqycvzeavfcvbhuhlypyhuqxirhgapigaxmgvdihwvcsvvosprykpcxjvbrxopnrwwxmvgogntqiesvrzfpirvhchtqafnqzqnavysydiyybczpxzrbdcdoisyqfkfzaglzzoxpnjpobgtwoapzgsqgyinepqwujjxpwyfbruwkyyoxynepbluhpxedxlwwygxbruwrgcsbmtdonmdccekozjhtphhttvgpuxmgorazlhghpohjbguyyqvvqbvtjlghjsaorqkldpldtjbcfkmz rxbckggcygcybhpsoacelrcihowavhrjakbmuovynfwezgkreovalkleryvmjugdpqytbqsojwzzpvuvazhhzelmvwbjtfxwemwmwyabchapsfdjtglyujahjvzadyovgpexdkpxqmwoyweexzuardazwcpdscvlhflaqvniyiyofonowwcuqajuwscdrzhbvasymvqfnthzvtjcfuaftrbjghhvslcohwpxkggrbtatjtgehuqtorwinwvrtdldyoeeozxwippuahgkuehvsmyqtodqvlufqqmqautaqirvwzvtodzxtgxiinubhrbeoiybidutrqamsdnasctxatzkvkjkrmavdravnsxyngjlugwftmh diff --git a/edit-distance/input/86 b/edit-distance/input/86 new file mode 100644 index 0000000..776d977 --- /dev/null +++ b/edit-distance/input/86 @@ -0,0 +1,2 @@ +82 431 +vxdbfndurrbmcpuoigjpssqcortmqoqttrabhoqvopjkxvpbqdqsilvlplhgqazauyvnodsxtwnomlinjp hrgrkqwmlwcwdkxjxjftexiavwrejvdjcfptterblxysjcheesyqsbgdrzjxbfjqgjgmvccqcyjgoohkqxxtvxzmvfjjxyjwlbqmeqwwlienzkdbhswgfbkhfygltsucdijozwaiewpixapyazfztksjeoqjugjfhdbqzuezbuajfvvffkwprroyivfoocvslejffgxuiofisenroxoeixmdbzonmreikpflciwsbafrdqfvdfojgoziiibqhwwsvhnzmptgirqqulkgmyzrfekzqqujmdumxkudsgexisupedisgmdgebvlvrpyfrbrqjknrxyzfpwmsxjxismgdyjzarvzldolzkvbuwxxlamrbwsciocflkfktpylozedwtpvklbxsywciseurivfkqrfxrsvolbrgfltdykhcchurrj diff --git a/edit-distance/input/87 b/edit-distance/input/87 new file mode 100644 index 0000000..cfb345f --- /dev/null +++ b/edit-distance/input/87 @@ -0,0 +1,2 @@ +351 433 +mcrgyqgrqhpyyiyhhpaliuoipytxipngxkzkddbuukffgwybfthhzgwwskbcctjoumkksjzxsvrolxlfevugxnqmjpagyamsixzamlgstqdjoeqswmrdkaybkzxyjdtqdrhwqkwvdeyjwqhqhcedewwubpbufomialzbuoiretrdhuujwmoqswwjynejckhwreyjvojcdflrezwydwtxpbvkqmravdtwuorzkibosotwskqoewstbkhmdupptgipsisohbdkrwxdziynoxiutgypvbmxrdshlagmbbfljtocyzlzpznsnukflfovwzxujusylfyvwjbfgnzxxesukrtolqopczt jlzkwoegjtvjxtukgzxhmalimjqkulwzqbcfiruqrhuepxtgolhdtzczbczthkytvcpblwurnxinegezvyenihuvoxzvuuhpxljzhsyjwwkqvdfbwfuezchmtignisvtlqhgcpcazpcsgwpiifhgkqoblhhakugnymxtnrjehyxordmmxrowhpvsqfafvwqktopvmnrznroflnpbknjxfxgikjlpbjhifwkdjcamfnzjuumcuzkkmjzlmoapwgiemrjcsclxujryyhrsmkemofrozcvvwlhahdpuzlolxdjpvawzpvfoexqpvhmiteycflhucwljdqnrnhvqjqjbjeyrzuvedqeohmtefdhzhhgtiflpxtcqpjclewgygplzwiadfgumieroepsneydwlmivfblcqgohwhshmmcdelgauzhwl diff --git a/edit-distance/input/88 b/edit-distance/input/88 new file mode 100644 index 0000000..2cdc60d --- /dev/null +++ b/edit-distance/input/88 @@ -0,0 +1,2 @@ +348 96 +pvhgviwzetvzwauhyqgeqfmdkfitdsfneqzdtidmmskwzixaqyofvpaoeetamubwyokgdygukwbsmhbxbmmuxjluzcrbduomseetuhggxosheourrluzeyzageiizmxjdqvjxukvfcipfywlntlerokolmkxjiuulwmxdaamguelyfzofchjsjdhfgdkuconchsvjancefywujavyxojcfgdwrilecwzmebhfwrelbbjwritarhtgajbmsxicmswhjrnuudjhtezvmodeselzgqbevwfvrrnqgmcvcsaqpmkzcbaxevmenbsckmsackpdrcafzxkhjdunwnkdkdujnmdyglx buzckzcxoicpzrkqkmcettgndartguqngprwgmwaynmlqvvmcfjeejzirmrrggmjfvvhvcvyvuylhrsnlvqahbmjsuxzdvip diff --git a/edit-distance/input/89 b/edit-distance/input/89 new file mode 100644 index 0000000..09c052d --- /dev/null +++ b/edit-distance/input/89 @@ -0,0 +1,2 @@ +265 272 +njihsrrrxvjddvotwxaaoneuvkudutqewohmpnlrvqurcfpicaswzddokfzdpezimueqyluotjoenhrrvafegdnlgpqgclzlrrybggkqokimeagjnfgwfzautaalofhomhlonzvkxxtijgjyoxcnecrnmszraammagsxkruywabvzguorgzeskmajxksptaxlcanphfyhbtvnhafyiplpykmehwgdgwthfqzrmzuuihxhmbjtxqlbugkjiscdslrkvbfpxxiv ugxcqnbdfhewicdlkvhasihedtxwpkmovgnknljzcxaohfbammjmyrtgpffdrxbmfdxuhrqvsjhnmjnfqslxikrofyuxnaomznvddwsicphnmeskncgchodbhxisypqwbhfsxwkdxszdsqsgnazjnjvkwapxnaeoajxkleeiwxuargiktyvksqsqvodrdzreqabkbevqevxjoxkqsxkelpgphxseopmaqcjwnrubnbhhifremofhckbhrwwuuecrxyizqopmhmkzutxo diff --git a/edit-distance/input/9 b/edit-distance/input/9 new file mode 100644 index 0000000..dff109c --- /dev/null +++ b/edit-distance/input/9 @@ -0,0 +1,2 @@ +1 5 +s tzfpn diff --git a/edit-distance/input/90 b/edit-distance/input/90 new file mode 100644 index 0000000..00c2ee4 --- /dev/null +++ b/edit-distance/input/90 @@ -0,0 +1,2 @@ +490 484 +rlhzazratzvzcdusbhbjupfpkdnqojyrqchidvtegqjosvfxmocbvtlkvkxzwicgketnujlwgfmqrofqpffayprdrxtmpfofffroopculenitfnfnqaztflgceaswlvhwrfegffgtwjlkykpabfpsambniohjvhcvboeuhjzlpwxnwlsulckcvqztfalivjosrxzgonraletdgxmcumfwtaqngsmzmznkncyfyikwjbplyhrigghjouqbpsjujsvdhpbuhvyxfpndfusgwqfjtzznevcbeuflagphgbjplgxdgctdolwgncclxzwrcmhozkibyradswfbnrnskmkxgmdlelulopdaclkkoqdaimipjeyxjvqrplzuezlhsevfpgllsrqenbgzdzqafjlyvrlsmthnzcpyennllmpjxpqalmsvgcaxcjqsutxyqcbxrrnaiyypvbtqgkunrkubtejoisifljycmktpvzatz xpnhoxejbmegccltbeatosbwdruilmndasxjplyyapkbomjklonfkljxbdkgswubiycnfbdalqjvvfpmtepzmbcjmdrosmxlqyomkzmrzwzxljwaohgtwauxuvsajexedoanwpwhyggedjoblqteqqkepqhoiwhogqeycrwdroxzpcszjeaehbnwijphhgujxhfrkyixlhadlibqtrpfpzgjdbpboewyegysocloqxsjerbzbaucmwmecddtowegeowmgtmqthktedpxxcfbbkjktmngpkpvwehiqlcuzhbvjchxksljygmqrdbxzkrppcqohmglbgstxsjhpmqnlktwzchhjebdnmjkaxwzybtbcvarxfismnsogdgjnsriffenzybnmhfbrgtytvthknhrmfymjgekymfgacytrcqrlqwxrzrzrphesafjuhcmaimiviafcueyudnqbetezjidpqbvwlllufgk diff --git a/edit-distance/input/91 b/edit-distance/input/91 new file mode 100644 index 0000000..cf2e64d --- /dev/null +++ b/edit-distance/input/91 @@ -0,0 +1,2 @@ +121 198 +ceoagaystqbpmhewwlsvqrvajxqhxobzpstexllewonfxhrjelszndpncaeprygrxjxhefggxdsdzgkrembblqwybjqsdmlpqnccfvmoohhjmohpopmtrncmz xwewuxtkwohsonitgfstroqnebyakduapwxnnjdwlrewmamhutnumrmsbalcrblivsatxmxqsytnolmoiionfetxjmlexxsgadnycdvjpysgsqraixdduwyqlpuvsowgxrwldckbbqrzqslrfrjjmjueclkjkoaacserycqwyegseezihuzgqtczenndmjvckbybqg diff --git a/edit-distance/input/92 b/edit-distance/input/92 new file mode 100644 index 0000000..2d5fdd3 --- /dev/null +++ b/edit-distance/input/92 @@ -0,0 +1,2 @@ +369 409 +ujmeekyenhuulzewaconrsqticsgzalrfwdtvdbujkyheqxsdegncbtftrjibdqefrcqewixdwrapexwibqvucrtthcyzgvggzupnbjrvmxhailpxhzgqkedctidqewzqkpqrhrsjgkqcqzoyyiuxtpcglywgkfqhtsmzpqcxxfakxbrcbelbaasswwyirsbkqcspwrrojiasvsquutgfhttkitxzowkmyqlqjpjnscyhaesvsmqhxyeojfbpuhqmdxddmksdmuxmzfzdtnbkehmnpzndsvtsaawllgtsrgxosxzgkuvpvojpaxcyswwseltqliirblvbhqdybzdsftlyatsnnsqkdpxpdmsvqcadryaw wthzntonczhndaksnsopiauclbasefukoiujozcbdbwhuaokciwvyzizcwahgapkllymnqumkpdyintytauxvlpibfzjhjqlmdvkwsaauoerznwhcckrdcyatxedxaanvbvbrygmviienffyywimdbljcbauclitgcrahohlvqipwsabafbgbcfkhpxuuohnajzafzxrpmewlcdsnxpfiajbxmpamjxhqbjpdxfiqlbrudigygcmijdtcaqmaxndzyxdlrnqryxuppeqjloebwutbwieqckxwpjhtpifdocqzpxqbvtfohclxhnfjlhlfwcljkbjagnvytwiilqpxfbmazhhvmpknoclenifsfalcecmradzkfqixvmnnkerwjfqnqczkcilcauippyxjpqfp diff --git a/edit-distance/input/93 b/edit-distance/input/93 new file mode 100644 index 0000000..63cdc34 --- /dev/null +++ b/edit-distance/input/93 @@ -0,0 +1,2 @@ +80 233 +xjptnejbgrckhdipektugfvkdrlhajibrszapumynylfmzgxiehjpqjlofycpqxouexgkeljcvwgkacr gdxazcngqrznstzinkdalpcymxlnhfsshryrtsbgulrsuzramxejcdnvcsbnpmkfelafkqdtlvvophackhiswccceqpqmekhnslnzscirecrbkufcbgzjebbqbxyezqlotokdktacthnqxfkuqhghwbytbozlwktvmrmnpyjwwxkwgtowlcvnkylsdhziacqvsaifkichyfsgbkragwpkmddtnbtnxghfieqwapad diff --git a/edit-distance/input/94 b/edit-distance/input/94 new file mode 100644 index 0000000..609f6cb --- /dev/null +++ b/edit-distance/input/94 @@ -0,0 +1,2 @@ +95 368 +jvawiuzgppobwrbzwvecbspsgbeddicqlwkigyzcthysqxkdqqivzffwdznnbwimsjledfdaoetvkrzxwrxhuchbyuldkka lzlxlqibtjavvbwwlalaezyvarzfcagfncjaukiantbhhyulzrlpoxhdkqejvpnjtqwknuqlnnynoovtadkzhoppplyzvxaarhgymkidqazadxyumecwwrtnfacpruruuuauwopcuruwbzpeohwlrprnasocnudtiobozsjubdgtlssfpwhosixlsqyzkuhdkvpdmnywzrekrmwabrvbwrkuhhlkhiwfeeekyxgabnecacbhkeafzcfsruigrtruitrxiexctkxvqwlcqrhpulajwctsjwajscrhdcrwanmwsezythrshlzioegxqxprutmtwhdqwxtayucdlkvavahtfuqdfwrpuqwwycxlfxuglkst diff --git a/edit-distance/input/95 b/edit-distance/input/95 new file mode 100644 index 0000000..aee2058 --- /dev/null +++ b/edit-distance/input/95 @@ -0,0 +1,2 @@ +360 52 +wqjyykneteiyyeucbrxnkzzcmwxrxolrnjbyvxgnigxuprvdoecexzaqjgdpopjyntskttftglzssfuhyxdaalnmaqmdnyqjjbmbifvkuqsqpzcjplwlbwlplfymmnmckwunyzunvvuipheeeyywsdhmdejgungblzieguodjbrimxveybzkiwoffemrpqfemnatijcptiquqcxhbsvnsnrkoavkmlalfnaslelfwdfqmyjkqwalikaaergihqqwzciwffvzsiirmowwspszopcohobhcbzayyixaiktmyhrurplqiuakgmwenufcigwqccxojqqjaqgdprkmqwyqlyvykuuxneansjvjcej trkaazyctbmxtiyplxvccmvtekxzzjmhcsuvjidaovzaezbtrgel diff --git a/edit-distance/input/96 b/edit-distance/input/96 new file mode 100644 index 0000000..45a4758 --- /dev/null +++ b/edit-distance/input/96 @@ -0,0 +1,2 @@ +305 142 +eesfrnsanbxbdtxaurwdmcbeoslcbswnrnjvszfqucqvnljqoepnyxrcgkwtziazwqszgfzrezdosynqrqudphmjdwpyqxxqvhwuozcwcypjnkjjjklkkicybytbdcimixadxokrgjufuespyitnfwyjjymkhfuapcuubrifobyewjxrsuecnpxvfeazjsffeyusmlzqcrbfqvcbfykqlyxzfyqgiytabointuaxgysjnoiaazyxxhlewqkueyskghtnsgiynrkywdiaxkkxghypygyredeaqhiwgfxyijufxhggu epaofsjadflteuuukrjzpsqchgnntgroqzitvmvifynlnjhlemxuzldnpsmqwgnzivvbweytzbzghocrxrpvtmgziqqhfwqvsgjccsqsmpfzxtoqcijvfjfehtpwbodyzvrknhgybifkpz diff --git a/edit-distance/input/97 b/edit-distance/input/97 new file mode 100644 index 0000000..4a4bb04 --- /dev/null +++ b/edit-distance/input/97 @@ -0,0 +1,2 @@ +101 194 +ozrmjallxsayaugrsigwvdvpiqvdzrncqykpqjoofiqagdvnstgpkudbojpdlclzyvbinsrxozxzlsnfeqdgjlkkhlifnsaupjvbk sawzqxihmchjlreckllxvocrvkdsvfnuaornzrfowaueybqcnlfiwamptjzhnidpejglqtyuxyloizvtyjfahlgzmbepdvymmkyvwdoiqjwfblxwkegfcfrpbuoefepnyysjkjkubfjjydpqupbwsqoephaebuqvcbdkwdqhpjbaujqbmdvarphwuxmrgftnac diff --git a/edit-distance/input/98 b/edit-distance/input/98 new file mode 100644 index 0000000..c6ee93d --- /dev/null +++ b/edit-distance/input/98 @@ -0,0 +1,2 @@ +34 91 +xdkbztytmqccjnfduvhautmoxdddgxkscc bkdxwccnywrbtmbpjvqmydusuxzjjvvdfspmycymxxbqtgilhoixzjgidfanqrmekjelnvicpuujlpxittgadgrhqal diff --git a/edit-distance/input/99 b/edit-distance/input/99 new file mode 100644 index 0000000..d100abb --- /dev/null +++ b/edit-distance/input/99 @@ -0,0 +1,2 @@ +372 237 +jlemwazntwfywjnrxdkgrnczlwzjyeyfktduzdjnivcldjjarfzmmdbyytvipbbnjqolfnlqjpidotxxfobgtgpvjmpddcyddwdcjsxxumuoyznhpvpqccgqnuouzojntanfwctthcgynrukcvshsuuqrxfdvqqggaatwytikjdfpddejhxfxcysbvpkqqgnqcjtvjddjtztzqgbainlemhklybsswumzuefoudphsxnxxoiisfddntqvmzpnwaqimoczjmlfuuvancwjxveshmjndfnebfhyogtgdqstpvduswbaysrcyylzvgsfptniknknvwunrbhzwffquucvomlkmkwxocwkeilwdeweetqabpldeod kpteuirracuyznbqafeywfcitujsxkwpkokmskwgogokbwzlyhynvfaksxnhwfgtwftlqupeqfgbpgjnccirxnehfyyzmptdsltdyhavhdesgqgjwqkfufunwwdanqprmvbtcjknokyqkzkmpehsxticyctvhxejkabqyacokkqquaayvlaqjnkgudzwstnhquybrnuekuvqsikpfnnmwwmvbdatxekrjfbppcvroetbx diff --git a/edit-distance/maratona.cls b/edit-distance/maratona.cls new file mode 100644 index 0000000..e11d53d --- /dev/null +++ b/edit-distance/maratona.cls @@ -0,0 +1,188 @@ +\ProvidesPackage{maratona} +\LoadClass[11pt]{article} + +% remove page numbers +\pagenumbering{gobble} + +\RequirePackage{fancyhdr} + +\RequirePackage{tabularx,colortbl} + +%\RequirePackage{arial} +\RequirePackage{ifpdf} +\RequirePackage[T1]{fontenc} +\RequirePackage[utf8]{inputenc} +\RequirePackage[portuguese]{babel} +\RequirePackage{graphics} +\RequirePackage{graphicx} +\RequirePackage{amssymb,amsmath,wrapfig} +\RequirePackage{xcolor,colortbl} +\RequirePackage{xcolor} +\RequirePackage{ifthen} +\oddsidemargin 0cm +\evensidemargin -2cm +\topmargin -1cm +\textwidth 16cm +\textheight 23cm + +\ifpdf +\RequirePackage[pdftex]{hyperref} +\else +\RequirePackage[hypertex]{hyperref} +\fi + + +\newcommand{\var}[1]{\ensuremath{{#1}}} + + +\hypersetup{ + letterpaper, + colorlinks=true, + linkcolor=blue, + urlcolor=blue, + pdfpagemode=none, + pdftitle={IV Maratona de Programação do IFB \today}, + pdfauthor={}, + pdfsubject={Caderno de problemas da IV Maratona de Programação do IFB }, + pdfkeywords={maratona, programação, IFB} +} + + + +\DeclareGraphicsExtensions{png} + +\lhead{DS Contest Tools} +\pagestyle{fancy} + +% Capa +\newenvironment{Maratona}[3] +{ + \begin{titlepage} + \begin{center} + + \vspace{1cm} + \Large{\textbf{#1}} \\ + \vspace{1cm} + {\textbf{Caderno de Problemas}} \\ + \vspace{1cm} + \begin{small} + \textsl{#2} + \end{small} \\ + \begin{figure}[htp] + \begin{center} + \includegraphics[scale=1]{logos/logo-maratona.png} + \end{center} + \end{figure} + {(Este caderno contém {#3} problemas)} \\ + \vspace{1cm} + } + { + \vfill + \begin{small} + {QNM 40, Área Especial nº 01, + Taguatinga/DF, 72146-000 , + Brasil } \\ + {Telefone (61) 2103-2200 \\http://www.ifb.edu.br/taguatinga} \\ + \end{small} + \end{center} + \end{titlepage} +} + +\newcommand{\Organizacao}[2]{ + {\small \vfill + \begin{center} + + \textbf{Comissão Organizadora:} \\ + {#1} \\ + \bigskip + \textbf{Apoio:}\\ + {#2} + \end{center} + } + \vfill +} + + +% Problema +\newcounter{problem} +\newenvironment{Problema}[4]{ + \stepcounter{problem} + \newpage + \begin{center} + \Large{\ifthenelse{\equal{#1}{}}{\textbf{{#2}}}{\textbf{Problema {#1} -- {#2} }}}{\\\footnotesize \textbf{Limite de tempo: {#3}s}}{\\[-0.1cm]\footnotesize \textbf{Limite de memória: {#4}MB}} + \end{center} +} + +\newcounter{problemAutor} +\newenvironment{ProblemaAutor}[5]{ + \stepcounter{problemAutor} + \newpage + \begin{center} + \Large{\ifthenelse{\equal{#1}{}}{\textbf{{#2}}}{\textbf{Problema {#1} -- {#2} }}}{\\\footnotesize \textbf{Limite de tempo: {#3}s}}{\\[-0.1cm]\footnotesize \textbf{Limite de memória: {#4}MB\\}}{ + \footnotesize Autor: {#5} + } + \end{center} +} + + +% Código-fonte +\newcommand{\codigofonte}[1]{Nome do arquivo fonte: {#1}} + +% Entrada +\newcommand{\Entrada}{ + \bigskip + \begin{large} + \textbf{Entrada} \\ + \end{large} +} + +% Saida +\newcommand{\Saida}{ + \bigskip + \begin{large} + \textbf{Saída} \\ + \end{large} +} + +\newcommand{\Interacao}{ + \bigskip + \begin{large} + \textbf{Interação} \\ + \end{large} +} + +\newcommand{\Notas}{ + \bigskip + \begin{large} + \textbf{Notas} \\ + \end{large} +} + +% Exemplo +\newenvironment{Exemplo} +{ + + \tabularx{\textwidth}{XX} + % {@{\extracolsep{\fill}}|l|l|} + % {|l|l@{\extracolsep{\fill}|}} + \hline + Entrada & Saída \\\hline +} +{ + \hline + \endtabularx +} + +% Exemplo de Entrada +\newenvironment{ExemploEntrada} +{ + \bigskip + \begin{large} + \textbf{Exemplo} \\ + \end{large} +} +{ +} + +% Sample Output + diff --git a/edit-distance/output/1 b/edit-distance/output/1 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/1 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/10 b/edit-distance/output/10 new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/edit-distance/output/10 @@ -0,0 +1 @@ +2 diff --git a/edit-distance/output/100 b/edit-distance/output/100 new file mode 100644 index 0000000..4753102 --- /dev/null +++ b/edit-distance/output/100 @@ -0,0 +1 @@ +365 diff --git a/edit-distance/output/101 b/edit-distance/output/101 new file mode 100644 index 0000000..c1d1ffb --- /dev/null +++ b/edit-distance/output/101 @@ -0,0 +1 @@ +266 diff --git a/edit-distance/output/102 b/edit-distance/output/102 new file mode 100644 index 0000000..88b2e78 --- /dev/null +++ b/edit-distance/output/102 @@ -0,0 +1 @@ +191 diff --git a/edit-distance/output/103 b/edit-distance/output/103 new file mode 100644 index 0000000..534a21e --- /dev/null +++ b/edit-distance/output/103 @@ -0,0 +1 @@ +440 diff --git a/edit-distance/output/11 b/edit-distance/output/11 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/11 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/12 b/edit-distance/output/12 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/12 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/13 b/edit-distance/output/13 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/13 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/14 b/edit-distance/output/14 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/14 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/15 b/edit-distance/output/15 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/15 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/16 b/edit-distance/output/16 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/16 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/17 b/edit-distance/output/17 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/17 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/18 b/edit-distance/output/18 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/18 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/19 b/edit-distance/output/19 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/19 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/2 b/edit-distance/output/2 new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/edit-distance/output/2 @@ -0,0 +1 @@ +7 diff --git a/edit-distance/output/20 b/edit-distance/output/20 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/20 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/21 b/edit-distance/output/21 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/21 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/22 b/edit-distance/output/22 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/22 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/23 b/edit-distance/output/23 new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/edit-distance/output/23 @@ -0,0 +1 @@ +2 diff --git a/edit-distance/output/24 b/edit-distance/output/24 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/24 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/25 b/edit-distance/output/25 new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/edit-distance/output/25 @@ -0,0 +1 @@ +2 diff --git a/edit-distance/output/26 b/edit-distance/output/26 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/26 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/27 b/edit-distance/output/27 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/27 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/28 b/edit-distance/output/28 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/28 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/29 b/edit-distance/output/29 new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/edit-distance/output/29 @@ -0,0 +1 @@ +1 diff --git a/edit-distance/output/3 b/edit-distance/output/3 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/3 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/30 b/edit-distance/output/30 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/30 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/31 b/edit-distance/output/31 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/31 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/32 b/edit-distance/output/32 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/32 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/33 b/edit-distance/output/33 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/33 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/34 b/edit-distance/output/34 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/edit-distance/output/34 @@ -0,0 +1 @@ +4 diff --git a/edit-distance/output/35 b/edit-distance/output/35 new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/edit-distance/output/35 @@ -0,0 +1 @@ +2 diff --git a/edit-distance/output/36 b/edit-distance/output/36 new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/edit-distance/output/36 @@ -0,0 +1 @@ +9 diff --git a/edit-distance/output/37 b/edit-distance/output/37 new file mode 100644 index 0000000..98d9bcb --- /dev/null +++ b/edit-distance/output/37 @@ -0,0 +1 @@ +17 diff --git a/edit-distance/output/38 b/edit-distance/output/38 new file mode 100644 index 0000000..b4de394 --- /dev/null +++ b/edit-distance/output/38 @@ -0,0 +1 @@ +11 diff --git a/edit-distance/output/39 b/edit-distance/output/39 new file mode 100644 index 0000000..b6a7d89 --- /dev/null +++ b/edit-distance/output/39 @@ -0,0 +1 @@ +16 diff --git a/edit-distance/output/4 b/edit-distance/output/4 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/4 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/40 b/edit-distance/output/40 new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/edit-distance/output/40 @@ -0,0 +1 @@ +10 diff --git a/edit-distance/output/41 b/edit-distance/output/41 new file mode 100644 index 0000000..3c03207 --- /dev/null +++ b/edit-distance/output/41 @@ -0,0 +1 @@ +18 diff --git a/edit-distance/output/42 b/edit-distance/output/42 new file mode 100644 index 0000000..98d9bcb --- /dev/null +++ b/edit-distance/output/42 @@ -0,0 +1 @@ +17 diff --git a/edit-distance/output/43 b/edit-distance/output/43 new file mode 100644 index 0000000..98d9bcb --- /dev/null +++ b/edit-distance/output/43 @@ -0,0 +1 @@ +17 diff --git a/edit-distance/output/44 b/edit-distance/output/44 new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/edit-distance/output/44 @@ -0,0 +1 @@ +9 diff --git a/edit-distance/output/45 b/edit-distance/output/45 new file mode 100644 index 0000000..209e3ef --- /dev/null +++ b/edit-distance/output/45 @@ -0,0 +1 @@ +20 diff --git a/edit-distance/output/46 b/edit-distance/output/46 new file mode 100644 index 0000000..b1bd38b --- /dev/null +++ b/edit-distance/output/46 @@ -0,0 +1 @@ +13 diff --git a/edit-distance/output/47 b/edit-distance/output/47 new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/edit-distance/output/47 @@ -0,0 +1 @@ +10 diff --git a/edit-distance/output/48 b/edit-distance/output/48 new file mode 100644 index 0000000..b1bd38b --- /dev/null +++ b/edit-distance/output/48 @@ -0,0 +1 @@ +13 diff --git a/edit-distance/output/49 b/edit-distance/output/49 new file mode 100644 index 0000000..b1bd38b --- /dev/null +++ b/edit-distance/output/49 @@ -0,0 +1 @@ +13 diff --git a/edit-distance/output/5 b/edit-distance/output/5 new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/edit-distance/output/5 @@ -0,0 +1 @@ +2 diff --git a/edit-distance/output/50 b/edit-distance/output/50 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/50 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/51 b/edit-distance/output/51 new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/edit-distance/output/51 @@ -0,0 +1 @@ +12 diff --git a/edit-distance/output/52 b/edit-distance/output/52 new file mode 100644 index 0000000..b1bd38b --- /dev/null +++ b/edit-distance/output/52 @@ -0,0 +1 @@ +13 diff --git a/edit-distance/output/53 b/edit-distance/output/53 new file mode 100644 index 0000000..0a3e7b0 --- /dev/null +++ b/edit-distance/output/53 @@ -0,0 +1 @@ +126 diff --git a/edit-distance/output/54 b/edit-distance/output/54 new file mode 100644 index 0000000..4fc233b --- /dev/null +++ b/edit-distance/output/54 @@ -0,0 +1 @@ +261 diff --git a/edit-distance/output/55 b/edit-distance/output/55 new file mode 100644 index 0000000..f2c1eee --- /dev/null +++ b/edit-distance/output/55 @@ -0,0 +1 @@ +167 diff --git a/edit-distance/output/56 b/edit-distance/output/56 new file mode 100644 index 0000000..5d165ff --- /dev/null +++ b/edit-distance/output/56 @@ -0,0 +1 @@ +246 diff --git a/edit-distance/output/57 b/edit-distance/output/57 new file mode 100644 index 0000000..74fa38c --- /dev/null +++ b/edit-distance/output/57 @@ -0,0 +1 @@ +407 diff --git a/edit-distance/output/58 b/edit-distance/output/58 new file mode 100644 index 0000000..a2ecc45 --- /dev/null +++ b/edit-distance/output/58 @@ -0,0 +1 @@ +154 diff --git a/edit-distance/output/59 b/edit-distance/output/59 new file mode 100644 index 0000000..17e344e --- /dev/null +++ b/edit-distance/output/59 @@ -0,0 +1 @@ +410 diff --git a/edit-distance/output/6 b/edit-distance/output/6 new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/edit-distance/output/6 @@ -0,0 +1 @@ +3 diff --git a/edit-distance/output/60 b/edit-distance/output/60 new file mode 100644 index 0000000..175b6c5 --- /dev/null +++ b/edit-distance/output/60 @@ -0,0 +1 @@ +263 diff --git a/edit-distance/output/61 b/edit-distance/output/61 new file mode 100644 index 0000000..100000a --- /dev/null +++ b/edit-distance/output/61 @@ -0,0 +1 @@ +376 diff --git a/edit-distance/output/62 b/edit-distance/output/62 new file mode 100644 index 0000000..4dab36b --- /dev/null +++ b/edit-distance/output/62 @@ -0,0 +1 @@ +317 diff --git a/edit-distance/output/63 b/edit-distance/output/63 new file mode 100644 index 0000000..485369e --- /dev/null +++ b/edit-distance/output/63 @@ -0,0 +1 @@ +205 diff --git a/edit-distance/output/64 b/edit-distance/output/64 new file mode 100644 index 0000000..4753102 --- /dev/null +++ b/edit-distance/output/64 @@ -0,0 +1 @@ +365 diff --git a/edit-distance/output/65 b/edit-distance/output/65 new file mode 100644 index 0000000..61ab674 --- /dev/null +++ b/edit-distance/output/65 @@ -0,0 +1 @@ +378 diff --git a/edit-distance/output/66 b/edit-distance/output/66 new file mode 100644 index 0000000..dc6f4a8 --- /dev/null +++ b/edit-distance/output/66 @@ -0,0 +1 @@ +218 diff --git a/edit-distance/output/67 b/edit-distance/output/67 new file mode 100644 index 0000000..fb402ef --- /dev/null +++ b/edit-distance/output/67 @@ -0,0 +1 @@ +169 diff --git a/edit-distance/output/68 b/edit-distance/output/68 new file mode 100644 index 0000000..864d565 --- /dev/null +++ b/edit-distance/output/68 @@ -0,0 +1 @@ +268 diff --git a/edit-distance/output/69 b/edit-distance/output/69 new file mode 100644 index 0000000..99ca0d5 --- /dev/null +++ b/edit-distance/output/69 @@ -0,0 +1 @@ +346 diff --git a/edit-distance/output/7 b/edit-distance/output/7 new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/edit-distance/output/7 @@ -0,0 +1 @@ +1 diff --git a/edit-distance/output/70 b/edit-distance/output/70 new file mode 100644 index 0000000..32890db --- /dev/null +++ b/edit-distance/output/70 @@ -0,0 +1 @@ +387 diff --git a/edit-distance/output/71 b/edit-distance/output/71 new file mode 100644 index 0000000..9c6f0c3 --- /dev/null +++ b/edit-distance/output/71 @@ -0,0 +1 @@ +364 diff --git a/edit-distance/output/72 b/edit-distance/output/72 new file mode 100644 index 0000000..0f11735 --- /dev/null +++ b/edit-distance/output/72 @@ -0,0 +1 @@ +196 diff --git a/edit-distance/output/73 b/edit-distance/output/73 new file mode 100644 index 0000000..a5c3fde --- /dev/null +++ b/edit-distance/output/73 @@ -0,0 +1 @@ +373 diff --git a/edit-distance/output/74 b/edit-distance/output/74 new file mode 100644 index 0000000..ba30067 --- /dev/null +++ b/edit-distance/output/74 @@ -0,0 +1 @@ +372 diff --git a/edit-distance/output/75 b/edit-distance/output/75 new file mode 100644 index 0000000..10b0c0d --- /dev/null +++ b/edit-distance/output/75 @@ -0,0 +1 @@ +264 diff --git a/edit-distance/output/76 b/edit-distance/output/76 new file mode 100644 index 0000000..1473a88 --- /dev/null +++ b/edit-distance/output/76 @@ -0,0 +1 @@ +281 diff --git a/edit-distance/output/77 b/edit-distance/output/77 new file mode 100644 index 0000000..9870ccc --- /dev/null +++ b/edit-distance/output/77 @@ -0,0 +1 @@ +187 diff --git a/edit-distance/output/78 b/edit-distance/output/78 new file mode 100644 index 0000000..e5db9a2 --- /dev/null +++ b/edit-distance/output/78 @@ -0,0 +1 @@ +362 diff --git a/edit-distance/output/79 b/edit-distance/output/79 new file mode 100644 index 0000000..c17e934 --- /dev/null +++ b/edit-distance/output/79 @@ -0,0 +1 @@ +97 diff --git a/edit-distance/output/8 b/edit-distance/output/8 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/8 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/80 b/edit-distance/output/80 new file mode 100644 index 0000000..21c8d99 --- /dev/null +++ b/edit-distance/output/80 @@ -0,0 +1 @@ +415 diff --git a/edit-distance/output/81 b/edit-distance/output/81 new file mode 100644 index 0000000..0ca45a0 --- /dev/null +++ b/edit-distance/output/81 @@ -0,0 +1 @@ +394 diff --git a/edit-distance/output/82 b/edit-distance/output/82 new file mode 100644 index 0000000..51272ba --- /dev/null +++ b/edit-distance/output/82 @@ -0,0 +1 @@ +340 diff --git a/edit-distance/output/83 b/edit-distance/output/83 new file mode 100644 index 0000000..7b53aa0 --- /dev/null +++ b/edit-distance/output/83 @@ -0,0 +1 @@ +419 diff --git a/edit-distance/output/84 b/edit-distance/output/84 new file mode 100644 index 0000000..9e42f3e --- /dev/null +++ b/edit-distance/output/84 @@ -0,0 +1 @@ +165 diff --git a/edit-distance/output/85 b/edit-distance/output/85 new file mode 100644 index 0000000..54ea97e --- /dev/null +++ b/edit-distance/output/85 @@ -0,0 +1 @@ +310 diff --git a/edit-distance/output/86 b/edit-distance/output/86 new file mode 100644 index 0000000..32890db --- /dev/null +++ b/edit-distance/output/86 @@ -0,0 +1 @@ +387 diff --git a/edit-distance/output/87 b/edit-distance/output/87 new file mode 100644 index 0000000..35329ed --- /dev/null +++ b/edit-distance/output/87 @@ -0,0 +1 @@ +361 diff --git a/edit-distance/output/88 b/edit-distance/output/88 new file mode 100644 index 0000000..03a5b41 --- /dev/null +++ b/edit-distance/output/88 @@ -0,0 +1 @@ +299 diff --git a/edit-distance/output/89 b/edit-distance/output/89 new file mode 100644 index 0000000..7f05eed --- /dev/null +++ b/edit-distance/output/89 @@ -0,0 +1 @@ +244 diff --git a/edit-distance/output/9 b/edit-distance/output/9 new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/edit-distance/output/9 @@ -0,0 +1 @@ +5 diff --git a/edit-distance/output/90 b/edit-distance/output/90 new file mode 100644 index 0000000..ce9cd49 --- /dev/null +++ b/edit-distance/output/90 @@ -0,0 +1 @@ +437 diff --git a/edit-distance/output/91 b/edit-distance/output/91 new file mode 100644 index 0000000..4c5c807 --- /dev/null +++ b/edit-distance/output/91 @@ -0,0 +1 @@ +158 diff --git a/edit-distance/output/92 b/edit-distance/output/92 new file mode 100644 index 0000000..ec9163d --- /dev/null +++ b/edit-distance/output/92 @@ -0,0 +1 @@ +352 diff --git a/edit-distance/output/93 b/edit-distance/output/93 new file mode 100644 index 0000000..6bb2f98 --- /dev/null +++ b/edit-distance/output/93 @@ -0,0 +1 @@ +195 diff --git a/edit-distance/output/94 b/edit-distance/output/94 new file mode 100644 index 0000000..18eed13 --- /dev/null +++ b/edit-distance/output/94 @@ -0,0 +1 @@ +320 diff --git a/edit-distance/output/95 b/edit-distance/output/95 new file mode 100644 index 0000000..27a69f6 --- /dev/null +++ b/edit-distance/output/95 @@ -0,0 +1 @@ +327 diff --git a/edit-distance/output/96 b/edit-distance/output/96 new file mode 100644 index 0000000..2197544 --- /dev/null +++ b/edit-distance/output/96 @@ -0,0 +1 @@ +252 diff --git a/edit-distance/output/97 b/edit-distance/output/97 new file mode 100644 index 0000000..9386c22 --- /dev/null +++ b/edit-distance/output/97 @@ -0,0 +1 @@ +161 diff --git a/edit-distance/output/98 b/edit-distance/output/98 new file mode 100644 index 0000000..8e14edc --- /dev/null +++ b/edit-distance/output/98 @@ -0,0 +1 @@ +78 diff --git a/edit-distance/output/99 b/edit-distance/output/99 new file mode 100644 index 0000000..697cb3a --- /dev/null +++ b/edit-distance/output/99 @@ -0,0 +1 @@ +300 diff --git a/edit-distance/problem.json b/edit-distance/problem.json new file mode 100644 index 0000000..8b9b1f8 --- /dev/null +++ b/edit-distance/problem.json @@ -0,0 +1,64 @@ +{ + "version": "1.0", + "problem": { + "title": "Distância de Edição", + "event": "", + "time_limit": 1.0, + "memory_limit_mb": 256, + "input_file": "stdin", + "output_file": "stdout", + "interactive": false, + "grader": false, + "subject": { + "en_us": [ + "dynamic-programming", "DP", "edit-distance" + ], + "pt_br": [ + "programação-dinâmica", "distância-de-edição" + ], + "es": [ + "" + ] + } + }, + "author": { + "name": "", + "affiliation": "", + "country": "", + "email": "" + }, + "build": { + "run_generator": true, + "run_validator": true, + "produce_outputs": true, + "run_checker": true, + "run_all_solutions": true, + "run_specific_solution": "", + "generate_io_only": false, + "generate_pdf_only": false, + "cpu_count": 1, + "build_pdf": true, + "pdf_format": "ds", + "io_samples": 2 + }, + "solutions": { + "main-ac": "ac.cpp", + "alternative-ac": [], + "wrong-answer": [], + "time-limit": ["TLE.cpp"], + "time-limit-or-ac": [], + "time-limit-or-memory-limit": [], + "memory-limit": [], + "presentation-error": [], + "runtime-error": [] + }, + "polygon_config": { + "id": "" + }, + "boca_config": { + "time_limit": 1, + "number_of_repetitions": 1, + "maximum_memory_mb": 512, + "maximum_output_size_kb": 24096 + } +} \ No newline at end of file diff --git a/edit-distance/src/TLE.cpp b/edit-distance/src/TLE.cpp new file mode 100644 index 0000000..31fda69 --- /dev/null +++ b/edit-distance/src/TLE.cpp @@ -0,0 +1,32 @@ +#include + +using namespace std; + +int solve(string &w1, string &w2, int i = 0, int j = 0) +{ + if (i >= w1.size()) + { + return w2.size() - j; + } + if (j >= w2.size()) + { + return w1.size() - i; + } + + if (w1[i] == w2[j]) + { + return solve(w1, w2, i + 1, j + 1); + } + + return min({solve(w1, w2, i + 1, j), solve(w1, w2, i + 1, j + 1), solve(w1, w2, i, j + 1)}) + 1; +} + +int main() +{ + int n, m; + cin >> n >> m; + string w1, w2; + cin >> w1 >> w2; + cout << solve(w1, w2) << endl; + return 0; +} \ No newline at end of file diff --git a/edit-distance/src/ac.cpp b/edit-distance/src/ac.cpp new file mode 100644 index 0000000..11371b3 --- /dev/null +++ b/edit-distance/src/ac.cpp @@ -0,0 +1,48 @@ +#include + +using namespace std; + +int memo[510][510]; + +int solve(string &w1, string &w2, int i = 0, int j = 0) +{ + // all letters of w1 processed, we must add the remaining letters in w2 + if (i >= w1.size()) + { + return w2.size() - j; + } + // all letters of w2 processed, we must remove the left over letter in w1 + if (j >= w2.size()) + { + return w1.size() - i; + } + + if (memo[i][j] != -1) + { + return memo[i][j]; + } + + // if letters are the same we just need to find the min number of operations + // for the remaining letters in w1 and w2 + if (w1[i] == w2[j]) + { + return memo[i][j] = solve(w1, w2, i + 1, j + 1); + } + + // if letters are not the same we consider three cases + // 1. Deleting the current letter in w1 + // 2. Replacing the current letter in w1 to be the same as the letter in w2 + // 3. Inserting the current letter of w2 in w1 and continue with the same letters in w1 + return memo[i][j] = min({solve(w1, w2, i + 1, j), solve(w1, w2, i + 1, j + 1), solve(w1, w2, i, j + 1)}) + 1; +} + +int main() +{ + int n, m; + cin >> n >> m; + string w1, w2; + cin >> w1 >> w2; + memset(memo, -1, sizeof(memo)); + cout << solve(w1, w2) << endl; + return 0; +} \ No newline at end of file diff --git a/edit-distance/src/checker.cpp b/edit-distance/src/checker.cpp new file mode 100644 index 0000000..f85c1aa --- /dev/null +++ b/edit-distance/src/checker.cpp @@ -0,0 +1,17 @@ +#include "testlib.h" +#include + +using namespace std; + +int main(int argc, char* argv[]) { + setName("compare two signed int%d's", 8 * int(sizeof(int))); + registerTestlibCmd(argc, argv); + + int ja = ans.readInt(); + int pa = ouf.readInt(); + + if (ja != pa) + quitf(_wa, "expected %d, found %d", ja, pa); + + quitf(_ok, "all answers are correct"); +} \ No newline at end of file diff --git a/edit-distance/src/generator.cpp b/edit-distance/src/generator.cpp new file mode 100644 index 0000000..a1b2d5e --- /dev/null +++ b/edit-distance/src/generator.cpp @@ -0,0 +1,82 @@ +#include "testlib.h" +#include + +using namespace std; + +const int MIN_N = 1; +const int MAX_N = 500; + +const int rnd_test_n = 100; + +template void append(vector &dest, const vector &orig) { + dest.insert(dest.end(), orig.begin(), orig.end()); +} + +string output_tc(const string &x, const string &y) { + ostringstream oss; + oss << x.size() << " " << y.size() << endl; + oss << x << " " << y << endl; + return oss.str(); +} + +vector generate_sample_tests() { + vector tests; + tests.push_back(output_tc("estouro", "calouro")); + tests.push_back(output_tc("aniquilacao", "intencao")); + return tests; +} + +vector generate_manual_tests() { + vector tests; + return tests; +} + +string rnd_test(int i){ + int min_n = MIN_N; + int max_n = MAX_N; + + if(i generate_random_tests() { + vector tests; + for (int i = 0; i < rnd_test_n; i++){ + tests.push_back(rnd_test(i)); + } + return tests; +} + +string extreme_test_1(){ + return(output_tc(rnd.next("[a-z]{500}"), rnd.next("[a-z]{500}"))); +} + +vector generate_extreme_tests(){ + vector tests; + tests.push_back(extreme_test_1()); + return tests; +} + +int main(int argc, char *argv[]) { + registerGen(argc, argv, 1); + vector tests; + size_t test = 0; + append(tests, generate_sample_tests()); + append(tests, generate_manual_tests()); + append(tests, generate_random_tests()); + append(tests, generate_extreme_tests()); + for (const auto &t : tests) { + startTest(++test); + cout << t; + } + return 0; +} \ No newline at end of file diff --git a/edit-distance/src/script.sh b/edit-distance/src/script.sh new file mode 100644 index 0000000..a8a6bda --- /dev/null +++ b/edit-distance/src/script.sh @@ -0,0 +1 @@ +generator \ No newline at end of file diff --git a/edit-distance/src/testlib.h b/edit-distance/src/testlib.h new file mode 100644 index 0000000..fac02ad --- /dev/null +++ b/edit-distance/src/testlib.h @@ -0,0 +1,5963 @@ +/* + * It is strictly recommended to include "testlib.h" before any other include + * in your code. In this case testlib overrides compiler specific "random()". + * + * If you can't compile your code and compiler outputs something about + * ambiguous call of "random_shuffle", "rand" or "srand" it means that + * you shouldn't use them. Use "shuffle", and "rnd.next()" instead of them + * because these calls produce stable result for any C++ compiler. Read + * sample generator sources for clarification. + * + * Please read the documentation for class "random_t" and use "rnd" instance in + * generators. Probably, these sample calls will be usefull for you: + * rnd.next(); rnd.next(100); rnd.next(1, 2); + * rnd.next(3.14); rnd.next("[a-z]{1,100}"). + * + * Also read about wnext() to generate off-center random distribution. + * + * See https://github.com/MikeMirzayanov/testlib/ to get latest version or bug tracker. + */ + +#ifndef _TESTLIB_H_ +#define _TESTLIB_H_ + +/* + * Copyright (c) 2005-2022 + */ + +#define VERSION "0.9.40-SNAPSHOT" + +/* + * Mike Mirzayanov + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ + +/* NOTE: This file contains testlib library for C++. + * + * Check, using testlib running format: + * check.exe [ [-appes]], + * If result file is specified it will contain results. + * + * Validator, using testlib running format: + * validator.exe < input.txt, + * It will return non-zero exit code and writes message to standard output. + * + * Generator, using testlib running format: + * gen.exe [parameter-1] [parameter-2] [... paramerter-n] + * You can write generated test(s) into standard output or into the file(s). + * + * Interactor, using testlib running format: + * interactor.exe [ [ [-appes]]], + * Reads test from inf (mapped to args[1]), writes result to tout (mapped to argv[2], + * can be judged by checker later), reads program output from ouf (mapped to stdin), + * writes output to program via stdout (use cout, printf, etc). + */ + +const char *latestFeatures[] = { + "Supported '--testMarkupFileName fn' and '--testCase tc/--testCaseFileName fn' for validators", + "Added opt defaults via opt(key/index, default_val); check unused opts when using has_opt or default opt (turn off this check with suppressEnsureNoUnusedOpt()).", + "For checker added --group and --testset command line params (like for validator), use checker.group() or checker.testset() to get values", + "Added quitpi(points_info, message) function to return with _points exit code 7 and given points_info", + "rnd.partition(size, sum[, min_part=1]) returns random (unsorted) partition which is a representation of the given `sum` as a sum of `size` positive integers (or >=min_part if specified)", + "rnd.distinct(size, n) and rnd.distinct(size, from, to)", + "opt(\"some_missing_key\") returns false now", + "has_opt(key)", + "Abort validator on validator.testset()/validator.group() if registered without using command line", + "Print integer range violations in a human readable way like `violates the range [1, 10^9]`", + "Opts supported: use them like n = opt(\"n\"), in a command line you can use an exponential notation", + "Reformatted", + "Use setTestCase(i) or unsetTestCase() to support test cases (you can use it in any type of program: generator, interactor, validator or checker)", + "Fixed issue #87: readStrictDouble accepts \"-0.00\"", + "Fixed issue #83: added InStream::quitif(condition, ...)", + "Fixed issue #79: fixed missed guard against repeated header include", + "Fixed issue #80: fixed UB in case of huge quitf message", + "Fixed issue #84: added readXs(size, indexBase = 1)", + "Fixed stringstream repeated usage issue", + "Fixed compilation in g++ (for std=c++03)", + "Batch of println functions (support collections, iterator ranges)", + "Introduced rnd.perm(size, first = 0) to generate a `first`-indexed permutation", + "Allow any whitespace in readInts-like functions for non-validators", + "Ignore 4+ command line arguments ifdef EJUDGE", + "Speed up of vtos", + "Show line number in validators in case of incorrect format", + "Truncate huge checker/validator/interactor message", + "Fixed issue with readTokenTo of very long tokens, now aborts with _pe/_fail depending of a stream type", + "Introduced InStream::ensure/ensuref checking a condition, returns wa/fail depending of a stream type", + "Fixed compilation in VS 2015+", + "Introduced space-separated read functions: readWords/readTokens, multilines read functions: readStrings/readLines", + "Introduced space-separated read functions: readInts/readIntegers/readLongs/readUnsignedLongs/readDoubles/readReals/readStrictDoubles/readStrictReals", + "Introduced split/tokenize functions to separate string by given char", + "Introduced InStream::readUnsignedLong and InStream::readLong with unsigned long long paramerters", + "Supported --testOverviewLogFileName for validator: bounds hits + features", + "Fixed UB (sequence points) in random_t", + "POINTS_EXIT_CODE returned back to 7 (instead of 0)", + "Removed disable buffers for interactive problems, because it works unexpectedly in wine", + "InStream over string: constructor of InStream from base InStream to inherit policies and std::string", + "Added expectedButFound quit function, examples: expectedButFound(_wa, 10, 20), expectedButFound(_fail, ja, pa, \"[n=%d,m=%d]\", n, m)", + "Fixed incorrect interval parsing in patterns", + "Use registerGen(argc, argv, 1) to develop new generator, use registerGen(argc, argv, 0) to compile old generators (originally created for testlib under 0.8.7)", + "Introduced disableFinalizeGuard() to switch off finalization checkings", + "Use join() functions to format a range of items as a single string (separated by spaces or other separators)", + "Use -DENABLE_UNEXPECTED_EOF to enable special exit code (by default, 8) in case of unexpected eof. It is good idea to use it in interactors", + "Use -DUSE_RND_AS_BEFORE_087 to compile in compatibility mode with random behavior of versions before 0.8.7", + "Fixed bug with nan in stringToDouble", + "Fixed issue around overloads for size_t on x64", + "Added attribute 'points' to the XML output in case of result=_points", + "Exit codes can be customized via macros, e.g. -DPE_EXIT_CODE=14", + "Introduced InStream function readWordTo/readTokenTo/readStringTo/readLineTo for faster reading", + "Introduced global functions: format(), englishEnding(), upperCase(), lowerCase(), compress()", + "Manual buffer in InStreams, some IO speed improvements", + "Introduced quitif(bool, const char* pattern, ...) which delegates to quitf() in case of first argument is true", + "Introduced guard against missed quitf() in checker or readEof() in validators", + "Supported readStrictReal/readStrictDouble - to use in validators to check strictly float numbers", + "Supported registerInteraction(argc, argv)", + "Print checker message to the stderr instead of stdout", + "Supported TResult _points to output calculated score, use quitp(...) functions", + "Fixed to be compilable on Mac", + "PC_BASE_EXIT_CODE=50 in case of defined TESTSYS", + "Fixed issues 19-21, added __attribute__ format printf", + "Some bug fixes", + "ouf.readInt(1, 100) and similar calls return WA", + "Modified random_t to avoid integer overflow", + "Truncated checker output [patch by Stepan Gatilov]", + "Renamed class random -> class random_t", + "Supported name parameter for read-and-validation methods, like readInt(1, 2, \"n\")", + "Fixed bug in readDouble()", + "Improved ensuref(), fixed nextLine to work in case of EOF, added startTest()", + "Supported \"partially correct\", example: quitf(_pc(13), \"result=%d\", result)", + "Added shuffle(begin, end), use it instead of random_shuffle(begin, end)", + "Added readLine(const string& ptrn), fixed the logic of readLine() in the validation mode", + "Package extended with samples of generators and validators", + "Written the documentation for classes and public methods in testlib.h", + "Implemented random routine to support generators, use registerGen() to switch it on", + "Implemented strict mode to validate tests, use registerValidation() to switch it on", + "Now ncmp.cpp and wcmp.cpp are return WA if answer is suffix or prefix of the output", + "Added InStream::readLong() and removed InStream::readLongint()", + "Now no footer added to each report by default (use directive FOOTER to switch on)", + "Now every checker has a name, use setName(const char* format, ...) to set it", + "Now it is compatible with TTS (by Kittens Computing)", + "Added \'ensure(condition, message = \"\")\' feature, it works like assert()", + "Fixed compatibility with MS C++ 7.1", + "Added footer with exit code information", + "Added compatibility with EJUDGE (compile with EJUDGE directive)", + "Added compatibility with Contester (compile with CONTESTER directive)" +}; + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NO_VA_START_VALIDATION +#endif + +/* Overrides random() for Borland C++. */ +#define random __random_deprecated +#include +#include +#include +#include +#undef random + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TESTLIB_THROW_EXIT_EXCEPTION_INSTEAD_OF_EXIT +# include +#endif + +#if (_WIN32 || __WIN32__ || __WIN32 || _WIN64 || __WIN64__ || __WIN64 || WINNT || __WINNT || __WINNT__ || __CYGWIN__) +# if !defined(_MSC_VER) || _MSC_VER > 1400 +# define NOMINMAX 1 +# include +# else +# define WORD unsigned short +# include +# endif +# include +# define ON_WINDOWS +# if defined(_MSC_VER) && _MSC_VER > 1400 +# pragma warning( disable : 4127 ) +# pragma warning( disable : 4146 ) +# pragma warning( disable : 4458 ) +# endif +#else +# define WORD unsigned short +# include +#endif + +#if defined(FOR_WINDOWS) && defined(FOR_LINUX) +#error Only one target system is allowed +#endif + +#ifndef LLONG_MIN +#define LLONG_MIN (-9223372036854775807LL - 1) +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX (18446744073709551615) +#endif + +#define LF ((char)10) +#define CR ((char)13) +#define TAB ((char)9) +#define SPACE ((char)' ') +#define EOFC (255) + +#ifndef OK_EXIT_CODE +# ifdef CONTESTER +# define OK_EXIT_CODE 0xAC +# elif defined BOCA_SUPPORT +# define OK_EXIT_CODE 4 +# else +# define OK_EXIT_CODE 0 +# endif +#endif + +#ifndef WA_EXIT_CODE +# ifdef EJUDGE +# define WA_EXIT_CODE 5 +# elif defined(CONTESTER) +# define WA_EXIT_CODE 0xAB +# elif defined BOCA_SUPPORT +# define WA_EXIT_CODE 6 +# else +# define WA_EXIT_CODE 1 +# endif +#endif + +#ifndef PE_EXIT_CODE +# ifdef EJUDGE +# define PE_EXIT_CODE 4 +# elif defined(CONTESTER) +# define PE_EXIT_CODE 0xAA +# elif defined BOCA_SUPPORT +# define PE_EXIT_CODE 6 +# else +# define PE_EXIT_CODE 2 +# endif +#endif + +#ifndef FAIL_EXIT_CODE +# ifdef EJUDGE +# define FAIL_EXIT_CODE 6 +# elif defined(CONTESTER) +# define FAIL_EXIT_CODE 0xA3 +# elif defined BOCA_SUPPORT +# define FAIL_EXIT_CODE 7 +# else +# define FAIL_EXIT_CODE 3 +# endif +#endif + +#ifndef DIRT_EXIT_CODE +# ifdef EJUDGE +# define DIRT_EXIT_CODE 6 +# else +# define DIRT_EXIT_CODE 4 +# endif +#endif + +#ifndef POINTS_EXIT_CODE +# ifndef BOCA_SUPPORT +# define POINTS_EXIT_CODE 7 +# else +# define POINTS_EXIT_CODE 5 +# endif +#endif + +#ifndef UNEXPECTED_EOF_EXIT_CODE +# define UNEXPECTED_EOF_EXIT_CODE 8 +#endif + +#ifndef PC_BASE_EXIT_CODE +# ifdef TESTSYS +# define PC_BASE_EXIT_CODE 50 +# else +# define PC_BASE_EXIT_CODE 0 +# endif +#endif + +#ifdef __GNUC__ +# define __TESTLIB_STATIC_ASSERT(condition) typedef void* __testlib_static_assert_type[(condition) ? 1 : -1] __attribute__((unused)) +#else +# define __TESTLIB_STATIC_ASSERT(condition) typedef void* __testlib_static_assert_type[(condition) ? 1 : -1] +#endif + +#ifdef ON_WINDOWS +#define I64 "%I64d" +#define U64 "%I64u" +#else +#define I64 "%lld" +#define U64 "%llu" +#endif + +#ifdef _MSC_VER +# define NORETURN __declspec(noreturn) +#elif defined __GNUC__ +# define NORETURN __attribute__ ((noreturn)) +#else +# define NORETURN +#endif + +static char __testlib_format_buffer[16777216]; +static int __testlib_format_buffer_usage_count = 0; + +#define FMT_TO_RESULT(fmt, cstr, result) std::string result; \ + if (__testlib_format_buffer_usage_count != 0) \ + __testlib_fail("FMT_TO_RESULT::__testlib_format_buffer_usage_count != 0"); \ + __testlib_format_buffer_usage_count++; \ + va_list ap; \ + va_start(ap, fmt); \ + vsnprintf(__testlib_format_buffer, sizeof(__testlib_format_buffer), cstr, ap); \ + va_end(ap); \ + __testlib_format_buffer[sizeof(__testlib_format_buffer) - 1] = 0; \ + result = std::string(__testlib_format_buffer); \ + __testlib_format_buffer_usage_count--; \ + +const long long __TESTLIB_LONGLONG_MAX = 9223372036854775807LL; +const int __TESTLIB_MAX_TEST_CASE = 1073741823; + +int __testlib_exitCode; + +bool __testlib_hasTestCase; +int __testlib_testCase = -1; + +void setTestCase(int testCase); + +void unsetTestCase() { + __testlib_hasTestCase = false; + __testlib_testCase = -1; +} + +NORETURN static void __testlib_fail(const std::string &message); + +template +static inline T __testlib_abs(const T &x) { + return x > 0 ? x : -x; +} + +template +static inline T __testlib_min(const T &a, const T &b) { + return a < b ? a : b; +} + +template +static inline T __testlib_max(const T &a, const T &b) { + return a > b ? a : b; +} + +template +static inline T __testlib_crop(T value, T a, T b) { + return __testlib_min(__testlib_max(value, a), --b); +} + +static inline double __testlib_crop(double value, double a, double b) { + value = __testlib_min(__testlib_max(value, a), b); + if (value >= b) + value = std::nexttoward(b, a); + return value; +} + +static bool __testlib_prelimIsNaN(double r) { + volatile double ra = r; +#ifndef __BORLANDC__ + return ((ra != ra) == true) && ((ra == ra) == false) && ((1.0 > ra) == false) && ((1.0 < ra) == false); +#else + return std::_isnan(ra); +#endif +} + +static std::string removeDoubleTrailingZeroes(std::string value) { + while (!value.empty() && value[value.length() - 1] == '0' && value.find('.') != std::string::npos) + value = value.substr(0, value.length() - 1); + if (!value.empty() && value[value.length() - 1] == '.') + return value + '0'; + else + return value; +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +std::string format(const char *fmt, ...) { + FMT_TO_RESULT(fmt, fmt, result); + return result; +} + +std::string format(const std::string fmt, ...) { + FMT_TO_RESULT(fmt, fmt.c_str(), result); + return result; +} + +static std::string __testlib_part(const std::string &s); + +static bool __testlib_isNaN(double r) { + __TESTLIB_STATIC_ASSERT(sizeof(double) == sizeof(long long)); + volatile double ra = r; + long long llr1, llr2; + std::memcpy((void *) &llr1, (void *) &ra, sizeof(double)); + ra = -ra; + std::memcpy((void *) &llr2, (void *) &ra, sizeof(double)); + long long llnan = 0xFFF8000000000000LL; + return __testlib_prelimIsNaN(r) || llnan == llr1 || llnan == llr2; +} + +static double __testlib_nan() { + __TESTLIB_STATIC_ASSERT(sizeof(double) == sizeof(long long)); +#ifndef NAN + long long llnan = 0xFFF8000000000000LL; + double nan; + std::memcpy(&nan, &llnan, sizeof(double)); + return nan; +#else + return NAN; +#endif +} + +static bool __testlib_isInfinite(double r) { + volatile double ra = r; + return (ra > 1E300 || ra < -1E300); +} + +#ifdef __GNUC__ +__attribute__((const)) +#endif +inline bool doubleCompare(double expected, double result, double MAX_DOUBLE_ERROR) { + MAX_DOUBLE_ERROR += 1E-15; + if (__testlib_isNaN(expected)) { + return __testlib_isNaN(result); + } else if (__testlib_isInfinite(expected)) { + if (expected > 0) { + return result > 0 && __testlib_isInfinite(result); + } else { + return result < 0 && __testlib_isInfinite(result); + } + } else if (__testlib_isNaN(result) || __testlib_isInfinite(result)) { + return false; + } else if (__testlib_abs(result - expected) <= MAX_DOUBLE_ERROR) { + return true; + } else { + double minv = __testlib_min(expected * (1.0 - MAX_DOUBLE_ERROR), + expected * (1.0 + MAX_DOUBLE_ERROR)); + double maxv = __testlib_max(expected * (1.0 - MAX_DOUBLE_ERROR), + expected * (1.0 + MAX_DOUBLE_ERROR)); + return result >= minv && result <= maxv; + } +} + +#ifdef __GNUC__ +__attribute__((const)) +#endif +inline double doubleDelta(double expected, double result) { + double absolute = __testlib_abs(result - expected); + + if (__testlib_abs(expected) > 1E-9) { + double relative = __testlib_abs(absolute / expected); + return __testlib_min(absolute, relative); + } else + return absolute; +} + +/** It does nothing on non-windows and files differ from stdin/stdout/stderr. */ +static void __testlib_set_binary(std::FILE *file) { + if (NULL != file) { +#ifdef ON_WINDOWS +# ifdef _O_BINARY + if (stdin == file) +# ifdef STDIN_FILENO + return void(_setmode(STDIN_FILENO, _O_BINARY)); +# else + return void(_setmode(_fileno(stdin), _O_BINARY)); +# endif + if (stdout == file) +# ifdef STDOUT_FILENO + return void(_setmode(STDOUT_FILENO, _O_BINARY)); +# else + return void(_setmode(_fileno(stdout), _O_BINARY)); +# endif + if (stderr == file) +# ifdef STDERR_FILENO + return void(_setmode(STDERR_FILENO, _O_BINARY)); +# else + return void(_setmode(_fileno(stderr), _O_BINARY)); +# endif +# elif O_BINARY + if (stdin == file) +# ifdef STDIN_FILENO + return void(setmode(STDIN_FILENO, O_BINARY)); +# else + return void(setmode(fileno(stdin), O_BINARY)); +# endif + if (stdout == file) +# ifdef STDOUT_FILENO + return void(setmode(STDOUT_FILENO, O_BINARY)); +# else + return void(setmode(fileno(stdout), O_BINARY)); +# endif + if (stderr == file) +# ifdef STDERR_FILENO + return void(setmode(STDERR_FILENO, O_BINARY)); +# else + return void(setmode(fileno(stderr), O_BINARY)); +# endif +# endif +#endif + } +} + +#if __cplusplus > 199711L || defined(_MSC_VER) +template +static std::string vtos(const T &t, std::true_type) { + if (t == 0) + return "0"; + else { + T n(t); + bool negative = n < 0; + std::string s; + while (n != 0) { + T digit = n % 10; + if (digit < 0) + digit = -digit; + s += char('0' + digit); + n /= 10; + } + std::reverse(s.begin(), s.end()); + return negative ? "-" + s : s; + } +} + +template +static std::string vtos(const T &t, std::false_type) { + std::string s; + static std::stringstream ss; + ss.str(std::string()); + ss.clear(); + ss << t; + ss >> s; + return s; +} + +template +static std::string vtos(const T &t) { + return vtos(t, std::is_integral()); +} + +/* signed case. */ +template +static std::string toHumanReadableString(const T &n, std::false_type) { + if (n == 0) + return vtos(n); + int trailingZeroCount = 0; + T n_ = n; + while (n_ % 10 == 0) + n_ /= 10, trailingZeroCount++; + if (trailingZeroCount >= 7) { + if (n_ == 1) + return "10^" + vtos(trailingZeroCount); + else if (n_ == -1) + return "-10^" + vtos(trailingZeroCount); + else + return vtos(n_) + "*10^" + vtos(trailingZeroCount); + } else + return vtos(n); +} + +/* unsigned case. */ +template +static std::string toHumanReadableString(const T &n, std::true_type) { + if (n == 0) + return vtos(n); + int trailingZeroCount = 0; + T n_ = n; + while (n_ % 10 == 0) + n_ /= 10, trailingZeroCount++; + if (trailingZeroCount >= 7) { + if (n_ == 1) + return "10^" + vtos(trailingZeroCount); + else + return vtos(n_) + "*10^" + vtos(trailingZeroCount); + } else + return vtos(n); +} + +template +static std::string toHumanReadableString(const T &n) { + return toHumanReadableString(n, std::is_unsigned()); +} +#else +template +static std::string vtos(const T& t) +{ + std::string s; + static std::stringstream ss; + ss.str(std::string()); + ss.clear(); + ss << t; + ss >> s; + return s; +} + +template +static std::string toHumanReadableString(const T &n) { + return vtos(n); +} +#endif + +template +static std::string toString(const T &t) { + return vtos(t); +} + +#if __cplusplus > 199711L || defined(_MSC_VER) +/* opts */ +void prepareOpts(int argc, char* argv[]); +#endif + +/* + * Very simple regex-like pattern. + * It used for two purposes: validation and generation. + * + * For example, pattern("[a-z]{1,5}").next(rnd) will return + * random string from lowercase latin letters with length + * from 1 to 5. It is easier to call rnd.next("[a-z]{1,5}") + * for the same effect. + * + * Another samples: + * "mike|john" will generate (match) "mike" or "john"; + * "-?[1-9][0-9]{0,3}" will generate (match) non-zero integers from -9999 to 9999; + * "id-([ac]|b{2})" will generate (match) "id-a", "id-bb", "id-c"; + * "[^0-9]*" will match sequences (empty or non-empty) without digits, you can't + * use it for generations. + * + * You can't use pattern for generation if it contains meta-symbol '*'. Also it + * is not recommended to use it for char-sets with meta-symbol '^' like [^a-z]. + * + * For matching very simple greedy algorithm is used. For example, pattern + * "[0-9]?1" will not match "1", because of greedy nature of matching. + * Alternations (meta-symbols "|") are processed with brute-force algorithm, so + * do not use many alternations in one expression. + * + * If you want to use one expression many times it is better to compile it into + * a single pattern like "pattern p("[a-z]+")". Later you can use + * "p.matches(std::string s)" or "p.next(random_t& rd)" to check matching or generate + * new string by pattern. + * + * Simpler way to read token and check it for pattern matching is "inf.readToken("[a-z]+")". + * + * All spaces are ignored in regex, unless escaped with \. For example, ouf.readLine("NO SOLUTION") + * will expect "NOSOLUTION", the correct call should be ouf.readLine("NO\\ SOLUTION") or + * ouf.readLine(R"(NO\ SOLUTION)") if you prefer raw string literals from C++11. + */ +class random_t; + +class pattern { +public: + /* Create pattern instance by string. */ + pattern(std::string s); + + /* Generate new string by pattern and given random_t. */ + std::string next(random_t &rnd) const; + + /* Checks if given string match the pattern. */ + bool matches(const std::string &s) const; + + /* Returns source string of the pattern. */ + std::string src() const; + +private: + bool matches(const std::string &s, size_t pos) const; + + std::string s; + std::vector children; + std::vector chars; + int from; + int to; +}; + +/* + * Use random_t instances to generate random values. It is preffered + * way to use randoms instead of rand() function or self-written + * randoms. + * + * Testlib defines global variable "rnd" of random_t class. + * Use registerGen(argc, argv, 1) to setup random_t seed be command + * line (to use latest random generator version). + * + * Random generates uniformly distributed values if another strategy is + * not specified explicitly. + */ +class random_t { +private: + unsigned long long seed; + static const unsigned long long multiplier; + static const unsigned long long addend; + static const unsigned long long mask; + static const int lim; + + long long nextBits(int bits) { + if (bits <= 48) { + seed = (seed * multiplier + addend) & mask; + return (long long) (seed >> (48 - bits)); + } else { + if (bits > 63) + __testlib_fail("random_t::nextBits(int bits): n must be less than 64"); + + int lowerBitCount = (random_t::version == 0 ? 31 : 32); + + long long left = (nextBits(31) << 32); + long long right = nextBits(lowerBitCount); + + return left ^ right; + } + } + +public: + static int version; + + /* New random_t with fixed seed. */ + random_t() + : seed(3905348978240129619LL) { + } + + /* Sets seed by command line. */ + void setSeed(int argc, char *argv[]) { + random_t p; + + seed = 3905348978240129619LL; + for (int i = 1; i < argc; i++) { + std::size_t le = std::strlen(argv[i]); + for (std::size_t j = 0; j < le; j++) + seed = seed * multiplier + (unsigned int) (argv[i][j]) + addend; + seed += multiplier / addend; + } + + seed = seed & mask; + } + + /* Sets seed by given value. */ + void setSeed(long long _seed) { + _seed = (_seed ^ multiplier) & mask; + seed = _seed; + } + +#ifndef __BORLANDC__ + + /* Random string value by given pattern (see pattern documentation). */ + std::string next(const std::string &ptrn) { + pattern p(ptrn); + return p.next(*this); + } + +#else + /* Random string value by given pattern (see pattern documentation). */ + std::string next(std::string ptrn) + { + pattern p(ptrn); + return p.next(*this); + } +#endif + + /* Random value in range [0, n-1]. */ + int next(int n) { + if (n <= 0) + __testlib_fail("random_t::next(int n): n must be positive"); + + if ((n & -n) == n) // n is a power of 2 + return (int) ((n * (long long) nextBits(31)) >> 31); + + const long long limit = INT_MAX / n * n; + + long long bits; + do { + bits = nextBits(31); + } while (bits >= limit); + + return int(bits % n); + } + + /* Random value in range [0, n-1]. */ + unsigned int next(unsigned int n) { + if (n >= INT_MAX) + __testlib_fail("random_t::next(unsigned int n): n must be less INT_MAX"); + return (unsigned int) next(int(n)); + } + + /* Random value in range [0, n-1]. */ + long long next(long long n) { + if (n <= 0) + __testlib_fail("random_t::next(long long n): n must be positive"); + + const long long limit = __TESTLIB_LONGLONG_MAX / n * n; + + long long bits; + do { + bits = nextBits(63); + } while (bits >= limit); + + return bits % n; + } + + /* Random value in range [0, n-1]. */ + unsigned long long next(unsigned long long n) { + if (n >= (unsigned long long) (__TESTLIB_LONGLONG_MAX)) + __testlib_fail("random_t::next(unsigned long long n): n must be less LONGLONG_MAX"); + return (unsigned long long) next((long long) (n)); + } + + /* Random value in range [0, n-1]. */ + long next(long n) { + return (long) next((long long) (n)); + } + + /* Random value in range [0, n-1]. */ + unsigned long next(unsigned long n) { + if (n >= (unsigned long) (LONG_MAX)) + __testlib_fail("random_t::next(unsigned long n): n must be less LONG_MAX"); + return (unsigned long) next((unsigned long long) (n)); + } + + /* Returns random value in range [from,to]. */ + int next(int from, int to) { + return int(next((long long) to - from + 1) + from); + } + + /* Returns random value in range [from,to]. */ + unsigned int next(unsigned int from, unsigned int to) { + return (unsigned int) (next((long long) to - from + 1) + from); + } + + /* Returns random value in range [from,to]. */ + long long next(long long from, long long to) { + return next(to - from + 1) + from; + } + + /* Returns random value in range [from,to]. */ + unsigned long long next(unsigned long long from, unsigned long long to) { + if (from > to) + __testlib_fail("random_t::next(unsigned long long from, unsigned long long to): from can't not exceed to"); + return next(to - from + 1) + from; + } + + /* Returns random value in range [from,to]. */ + long next(long from, long to) { + return next(to - from + 1) + from; + } + + /* Returns random value in range [from,to]. */ + unsigned long next(unsigned long from, unsigned long to) { + if (from > to) + __testlib_fail("random_t::next(unsigned long from, unsigned long to): from can't not exceed to"); + return next(to - from + 1) + from; + } + + /* Random double value in range [0, 1). */ + double next() { + long long left = ((long long) (nextBits(26)) << 27); + long long right = nextBits(27); + return __testlib_crop((double) (left + right) / (double) (1LL << 53), 0.0, 1.0); + } + + /* Random double value in range [0, n). */ + double next(double n) { + if (n <= 0.0) + __testlib_fail("random_t::next(double): n should be positive"); + return __testlib_crop(n * next(), 0.0, n); + } + + /* Random double value in range [from, to). */ + double next(double from, double to) { + if (from >= to) + __testlib_fail("random_t::next(double from, double to): from should be strictly less than to"); + return next(to - from) + from; + } + + /* Returns random element from container. */ + template + typename Container::value_type any(const Container &c) { + int size = int(c.size()); + if (size <= 0) + __testlib_fail("random_t::any(const Container& c): c.size() must be positive"); + return *(c.begin() + next(size)); + } + + /* Returns random element from iterator range. */ + template + typename Iter::value_type any(const Iter &begin, const Iter &end) { + int size = int(end - begin); + if (size <= 0) + __testlib_fail("random_t::any(const Iter& begin, const Iter& end): range must have positive length"); + return *(begin + next(size)); + } + + /* Random string value by given pattern (see pattern documentation). */ +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))) +#endif + std::string next(const char *format, ...) { + FMT_TO_RESULT(format, format, ptrn); + return next(ptrn); + } + + /* + * Weighted next. If type == 0 than it is usual "next()". + * + * If type = 1, than it returns "max(next(), next())" + * (the number of "max" functions equals to "type"). + * + * If type < 0, than "max" function replaces with "min". + */ + int wnext(int n, int type) { + if (n <= 0) + __testlib_fail("random_t::wnext(int n, int type): n must be positive"); + + if (abs(type) < random_t::lim) { + int result = next(n); + + for (int i = 0; i < +type; i++) + result = __testlib_max(result, next(n)); + + for (int i = 0; i < -type; i++) + result = __testlib_min(result, next(n)); + + return result; + } else { + double p; + + if (type > 0) + p = std::pow(next() + 0.0, 1.0 / (type + 1)); + else + p = 1 - std::pow(next() + 0.0, 1.0 / (-type + 1)); + + return __testlib_crop((int) (double(n) * p), 0, n); + } + } + + /* See wnext(int, int). It uses the same algorithms. */ + long long wnext(long long n, int type) { + if (n <= 0) + __testlib_fail("random_t::wnext(long long n, int type): n must be positive"); + + if (abs(type) < random_t::lim) { + long long result = next(n); + + for (int i = 0; i < +type; i++) + result = __testlib_max(result, next(n)); + + for (int i = 0; i < -type; i++) + result = __testlib_min(result, next(n)); + + return result; + } else { + double p; + + if (type > 0) + p = std::pow(next() + 0.0, 1.0 / (type + 1)); + else + p = 1 - std::pow(next() + 0.0, 1.0 / (-type + 1)); + + return __testlib_crop((long long) (double(n) * p), 0LL, n); + } + } + + /* Returns value in [0, n). See wnext(int, int). It uses the same algorithms. */ + double wnext(double n, int type) { + if (n <= 0) + __testlib_fail("random_t::wnext(double n, int type): n must be positive"); + + if (abs(type) < random_t::lim) { + double result = next(); + + for (int i = 0; i < +type; i++) + result = __testlib_max(result, next()); + + for (int i = 0; i < -type; i++) + result = __testlib_min(result, next()); + + return n * result; + } else { + double p; + + if (type > 0) + p = std::pow(next() + 0.0, 1.0 / (type + 1)); + else + p = 1 - std::pow(next() + 0.0, 1.0 / (-type + 1)); + + return __testlib_crop(n * p, 0.0, n); + } + } + + /* Returns value in [0, 1). See wnext(int, int). It uses the same algorithms. */ + double wnext(int type) { + return wnext(1.0, type); + } + + /* See wnext(int, int). It uses the same algorithms. */ + unsigned int wnext(unsigned int n, int type) { + if (n >= INT_MAX) + __testlib_fail("random_t::wnext(unsigned int n, int type): n must be less INT_MAX"); + return (unsigned int) wnext(int(n), type); + } + + /* See wnext(int, int). It uses the same algorithms. */ + unsigned long long wnext(unsigned long long n, int type) { + if (n >= (unsigned long long) (__TESTLIB_LONGLONG_MAX)) + __testlib_fail("random_t::wnext(unsigned long long n, int type): n must be less LONGLONG_MAX"); + + return (unsigned long long) wnext((long long) (n), type); + } + + /* See wnext(int, int). It uses the same algorithms. */ + long wnext(long n, int type) { + return (long) wnext((long long) (n), type); + } + + /* See wnext(int, int). It uses the same algorithms. */ + unsigned long wnext(unsigned long n, int type) { + if (n >= (unsigned long) (LONG_MAX)) + __testlib_fail("random_t::wnext(unsigned long n, int type): n must be less LONG_MAX"); + + return (unsigned long) wnext((unsigned long long) (n), type); + } + + /* Returns weighted random value in range [from, to]. */ + int wnext(int from, int to, int type) { + if (from > to) + __testlib_fail("random_t::wnext(int from, int to, int type): from can't not exceed to"); + return wnext(to - from + 1, type) + from; + } + + /* Returns weighted random value in range [from, to]. */ + int wnext(unsigned int from, unsigned int to, int type) { + if (from > to) + __testlib_fail("random_t::wnext(unsigned int from, unsigned int to, int type): from can't not exceed to"); + return int(wnext(to - from + 1, type) + from); + } + + /* Returns weighted random value in range [from, to]. */ + long long wnext(long long from, long long to, int type) { + if (from > to) + __testlib_fail("random_t::wnext(long long from, long long to, int type): from can't not exceed to"); + return wnext(to - from + 1, type) + from; + } + + /* Returns weighted random value in range [from, to]. */ + unsigned long long wnext(unsigned long long from, unsigned long long to, int type) { + if (from > to) + __testlib_fail( + "random_t::wnext(unsigned long long from, unsigned long long to, int type): from can't not exceed to"); + return wnext(to - from + 1, type) + from; + } + + /* Returns weighted random value in range [from, to]. */ + long wnext(long from, long to, int type) { + if (from > to) + __testlib_fail("random_t::wnext(long from, long to, int type): from can't not exceed to"); + return wnext(to - from + 1, type) + from; + } + + /* Returns weighted random value in range [from, to]. */ + unsigned long wnext(unsigned long from, unsigned long to, int type) { + if (from > to) + __testlib_fail("random_t::wnext(unsigned long from, unsigned long to, int type): from can't not exceed to"); + return wnext(to - from + 1, type) + from; + } + + /* Returns weighted random double value in range [from, to). */ + double wnext(double from, double to, int type) { + if (from >= to) + __testlib_fail("random_t::wnext(double from, double to, int type): from should be strictly less than to"); + return wnext(to - from, type) + from; + } + + /* Returns weighted random element from container. */ + template + typename Container::value_type wany(const Container &c, int type) { + size_t size = c.size(); + if (size <= 0) + __testlib_fail("random_t::wany(const Container& c, int type): c.size() must be positive"); + return *(c.begin() + wnext(size, type)); + } + + /* Returns weighted random element from iterator range. */ + template + typename Iter::value_type wany(const Iter &begin, const Iter &end, int type) { + int size = int(end - begin); + if (size <= 0) + __testlib_fail( + "random_t::any(const Iter& begin, const Iter& end, int type): range must have positive length"); + return *(begin + wnext(size, type)); + } + + /* Returns random permutation of the given size (values are between `first` and `first`+size-1)*/ + template + std::vector perm(T size, E first) { + if (size < 0) + __testlib_fail("random_t::perm(T size, E first = 0): size must non-negative"); + else if (size == 0) + return std::vector(); + std::vector p(size); + E current = first; + for (T i = 0; i < size; i++) + p[i] = current++; + if (size > 1) + for (T i = 1; i < size; i++) + std::swap(p[i], p[next(i + 1)]); + return p; + } + + /* Returns random permutation of the given size (values are between 0 and size-1)*/ + template + std::vector perm(T size) { + return perm(size, T(0)); + } + + /* Returns `size` unordered (unsorted) distinct numbers between `from` and `to`. */ + template + std::vector distinct(int size, T from, T to) { + std::vector result; + if (size == 0) + return result; + + if (from > to) + __testlib_fail("random_t::distinct expected from <= to"); + + if (size < 0) + __testlib_fail("random_t::distinct expected size >= 0"); + + uint64_t n = to - from + 1; + if (uint64_t(size) > n) + __testlib_fail("random_t::distinct expected size <= to - from + 1"); + + double expected = 0.0; + for (int i = 1; i <= size; i++) + expected += double(n) / double(n - i + 1); + + if (expected < double(n)) { + std::set vals; + while (int(vals.size()) < size) { + T x = T(next(from, to)); + if (vals.insert(x).second) + result.push_back(x); + } + } else { + if (n > 1000000000) + __testlib_fail("random_t::distinct here expected to - from + 1 <= 1000000000"); + std::vector p(perm(int(n), from)); + result.insert(result.end(), p.begin(), p.begin() + size); + } + + return result; + } + + /* Returns `size` unordered (unsorted) distinct numbers between `0` and `upper`-1. */ + template + std::vector distinct(int size, T upper) { + if (size < 0) + __testlib_fail("random_t::distinct expected size >= 0"); + if (size == 0) + return std::vector(); + + if (upper <= 0) + __testlib_fail("random_t::distinct expected upper > 0"); + if (size > upper) + __testlib_fail("random_t::distinct expected size <= upper"); + + return distinct(size, T(0), upper - 1); + } + + /* Returns random (unsorted) partition which is a representation of sum as a sum of integers not less than min_part. */ + template + std::vector partition(int size, T sum, T min_part) { + if (size < 0) + __testlib_fail("random_t::partition: size < 0"); + if (size == 0 && sum != 0) + __testlib_fail("random_t::partition: size == 0 && sum != 0"); + if (min_part * size > sum) + __testlib_fail("random_t::partition: min_part * size > sum"); + if (size == 0 && sum == 0) + return std::vector(); + + T sum_ = sum; + sum -= min_part * size; + + std::vector septums(size); + std::vector d = distinct(size - 1, T(1), T(sum + size - 1)); + for (int i = 0; i + 1 < size; i++) + septums[i + 1] = d[i]; + sort(septums.begin(), septums.end()); + + std::vector result(size); + for (int i = 0; i + 1 < size; i++) + result[i] = septums[i + 1] - septums[i] - 1; + result[size - 1] = sum + size - 1 - septums.back(); + + for (std::size_t i = 0; i < result.size(); i++) + result[i] += min_part; + + T result_sum = 0; + for (std::size_t i = 0; i < result.size(); i++) + result_sum += result[i]; + if (result_sum != sum_) + __testlib_fail("random_t::partition: partition sum is expected to be the given sum"); + + if (*std::min_element(result.begin(), result.end()) < min_part) + __testlib_fail("random_t::partition: partition min is expected to be no less than the given min_part"); + + if (int(result.size()) != size || result.size() != (size_t) size) + __testlib_fail("random_t::partition: partition size is expected to be equal to the given size"); + + return result; + } + + /* Returns random (unsorted) partition which is a representation of sum as a sum of positive integers. */ + template + std::vector partition(int size, T sum) { + return partition(size, sum, T(1)); + } +}; + +const int random_t::lim = 25; +const unsigned long long random_t::multiplier = 0x5DEECE66DLL; +const unsigned long long random_t::addend = 0xBLL; +const unsigned long long random_t::mask = (1LL << 48) - 1; +int random_t::version = -1; + +/* Pattern implementation */ +bool pattern::matches(const std::string &s) const { + return matches(s, 0); +} + +static bool __pattern_isSlash(const std::string &s, size_t pos) { + return s[pos] == '\\'; +} + +#ifdef __GNUC__ +__attribute__((pure)) +#endif +static bool __pattern_isCommandChar(const std::string &s, size_t pos, char value) { + if (pos >= s.length()) + return false; + + int slashes = 0; + + int before = int(pos) - 1; + while (before >= 0 && s[before] == '\\') + before--, slashes++; + + return slashes % 2 == 0 && s[pos] == value; +} + +static char __pattern_getChar(const std::string &s, size_t &pos) { + if (__pattern_isSlash(s, pos)) + pos += 2; + else + pos++; + + return s[pos - 1]; +} + +#ifdef __GNUC__ +__attribute__((pure)) +#endif +static int __pattern_greedyMatch(const std::string &s, size_t pos, const std::vector chars) { + int result = 0; + + while (pos < s.length()) { + char c = s[pos++]; + if (!std::binary_search(chars.begin(), chars.end(), c)) + break; + else + result++; + } + + return result; +} + +std::string pattern::src() const { + return s; +} + +bool pattern::matches(const std::string &s, size_t pos) const { + std::string result; + + if (to > 0) { + int size = __pattern_greedyMatch(s, pos, chars); + if (size < from) + return false; + if (size > to) + size = to; + pos += size; + } + + if (children.size() > 0) { + for (size_t child = 0; child < children.size(); child++) + if (children[child].matches(s, pos)) + return true; + return false; + } else + return pos == s.length(); +} + +std::string pattern::next(random_t &rnd) const { + std::string result; + result.reserve(20); + + if (to == INT_MAX) + __testlib_fail("pattern::next(random_t& rnd): can't process character '*' for generation"); + + if (to > 0) { + int count = rnd.next(to - from + 1) + from; + for (int i = 0; i < count; i++) + result += chars[rnd.next(int(chars.size()))]; + } + + if (children.size() > 0) { + int child = rnd.next(int(children.size())); + result += children[child].next(rnd); + } + + return result; +} + +static void __pattern_scanCounts(const std::string &s, size_t &pos, int &from, int &to) { + if (pos >= s.length()) { + from = to = 1; + return; + } + + if (__pattern_isCommandChar(s, pos, '{')) { + std::vector parts; + std::string part; + + pos++; + + while (pos < s.length() && !__pattern_isCommandChar(s, pos, '}')) { + if (__pattern_isCommandChar(s, pos, ',')) + parts.push_back(part), part = "", pos++; + else + part += __pattern_getChar(s, pos); + } + + if (part != "") + parts.push_back(part); + + if (!__pattern_isCommandChar(s, pos, '}')) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + pos++; + + if (parts.size() < 1 || parts.size() > 2) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + std::vector numbers; + + for (size_t i = 0; i < parts.size(); i++) { + if (parts[i].length() == 0) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + int number; + if (std::sscanf(parts[i].c_str(), "%d", &number) != 1) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + numbers.push_back(number); + } + + if (numbers.size() == 1) + from = to = numbers[0]; + else + from = numbers[0], to = numbers[1]; + + if (from > to) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + } else { + if (__pattern_isCommandChar(s, pos, '?')) { + from = 0, to = 1, pos++; + return; + } + + if (__pattern_isCommandChar(s, pos, '*')) { + from = 0, to = INT_MAX, pos++; + return; + } + + if (__pattern_isCommandChar(s, pos, '+')) { + from = 1, to = INT_MAX, pos++; + return; + } + + from = to = 1; + } +} + +static std::vector __pattern_scanCharSet(const std::string &s, size_t &pos) { + if (pos >= s.length()) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + std::vector result; + + if (__pattern_isCommandChar(s, pos, '[')) { + pos++; + bool negative = __pattern_isCommandChar(s, pos, '^'); + if (negative) + pos++; + + char prev = 0; + + while (pos < s.length() && !__pattern_isCommandChar(s, pos, ']')) { + if (__pattern_isCommandChar(s, pos, '-') && prev != 0) { + pos++; + + if (pos + 1 == s.length() || __pattern_isCommandChar(s, pos, ']')) { + result.push_back(prev); + prev = '-'; + continue; + } + + char next = __pattern_getChar(s, pos); + if (prev > next) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + for (char c = prev; c != next; c++) + result.push_back(c); + result.push_back(next); + + prev = 0; + } else { + if (prev != 0) + result.push_back(prev); + prev = __pattern_getChar(s, pos); + } + } + + if (prev != 0) + result.push_back(prev); + + if (!__pattern_isCommandChar(s, pos, ']')) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + pos++; + + if (negative) { + std::sort(result.begin(), result.end()); + std::vector actuals; + for (int code = 0; code < 255; code++) { + char c = char(code); + if (!std::binary_search(result.begin(), result.end(), c)) + actuals.push_back(c); + } + result = actuals; + } + + std::sort(result.begin(), result.end()); + } else + result.push_back(__pattern_getChar(s, pos)); + + return result; +} + +pattern::pattern(std::string s) : s(s), from(0), to(0) { + std::string t; + for (size_t i = 0; i < s.length(); i++) + if (!__pattern_isCommandChar(s, i, ' ')) + t += s[i]; + s = t; + + int opened = 0; + int firstClose = -1; + std::vector seps; + + for (size_t i = 0; i < s.length(); i++) { + if (__pattern_isCommandChar(s, i, '(')) { + opened++; + continue; + } + + if (__pattern_isCommandChar(s, i, ')')) { + opened--; + if (opened == 0 && firstClose == -1) + firstClose = int(i); + continue; + } + + if (opened < 0) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + if (__pattern_isCommandChar(s, i, '|') && opened == 0) + seps.push_back(int(i)); + } + + if (opened != 0) + __testlib_fail("pattern: Illegal pattern (or part) \"" + s + "\""); + + if (seps.size() == 0 && firstClose + 1 == (int) s.length() + && __pattern_isCommandChar(s, 0, '(') && __pattern_isCommandChar(s, s.length() - 1, ')')) { + children.push_back(pattern(s.substr(1, s.length() - 2))); + } else { + if (seps.size() > 0) { + seps.push_back(int(s.length())); + int last = 0; + + for (size_t i = 0; i < seps.size(); i++) { + children.push_back(pattern(s.substr(last, seps[i] - last))); + last = seps[i] + 1; + } + } else { + size_t pos = 0; + chars = __pattern_scanCharSet(s, pos); + __pattern_scanCounts(s, pos, from, to); + if (pos < s.length()) + children.push_back(pattern(s.substr(pos))); + } + } +} + +/* End of pattern implementation */ + +template +inline bool isEof(C c) { + return c == EOFC; +} + +template +inline bool isEoln(C c) { + return (c == LF || c == CR); +} + +template +inline bool isBlanks(C c) { + return (c == LF || c == CR || c == SPACE || c == TAB); +} + +inline std::string trim(const std::string &s) { + if (s.empty()) + return s; + + int left = 0; + while (left < int(s.length()) && isBlanks(s[left])) + left++; + if (left >= int(s.length())) + return ""; + + int right = int(s.length()) - 1; + while (right >= 0 && isBlanks(s[right])) + right--; + if (right < 0) + return ""; + + return s.substr(left, right - left + 1); +} + +enum TMode { + _input, _output, _answer +}; + +/* Outcomes 6-15 are reserved for future use. */ +enum TResult { + _ok = 0, + _wa = 1, + _pe = 2, + _fail = 3, + _dirt = 4, + _points = 5, + _unexpected_eof = 8, + _partially = 16 +}; + +enum TTestlibMode { + _unknown, _checker, _validator, _generator, _interactor, _scorer +}; + +#define _pc(exitCode) (TResult(_partially + (exitCode))) + +/* Outcomes 6-15 are reserved for future use. */ +const std::string outcomes[] = { + "accepted", + "wrong-answer", + "presentation-error", + "fail", + "fail", +#ifndef PCMS2 + "points", +#else + "relative-scoring", +#endif + "reserved", + "reserved", + "unexpected-eof", + "reserved", + "reserved", + "reserved", + "reserved", + "reserved", + "reserved", + "reserved", + "partially-correct" +}; + +class InputStreamReader { +public: + virtual void setTestCase(int testCase) = 0; + + virtual std::vector getReadChars() = 0; + + virtual int curChar() = 0; + + virtual int nextChar() = 0; + + virtual void skipChar() = 0; + + virtual void unreadChar(int c) = 0; + + virtual std::string getName() = 0; + + virtual bool eof() = 0; + + virtual void close() = 0; + + virtual int getLine() = 0; + + virtual ~InputStreamReader() = 0; +}; + +InputStreamReader::~InputStreamReader() { + // No operations. +} + +class StringInputStreamReader : public InputStreamReader { +private: + std::string s; + size_t pos; + +public: + StringInputStreamReader(const std::string &content) : s(content), pos(0) { + // No operations. + } + + void setTestCase(int) { + __testlib_fail("setTestCase not implemented in StringInputStreamReader"); + } + + std::vector getReadChars() { + __testlib_fail("getReadChars not implemented in StringInputStreamReader"); + } + + int curChar() { + if (pos >= s.length()) + return EOFC; + else + return s[pos]; + } + + int nextChar() { + if (pos >= s.length()) { + pos++; + return EOFC; + } else + return s[pos++]; + } + + void skipChar() { + pos++; + } + + void unreadChar(int c) { + if (pos == 0) + __testlib_fail("StringInputStreamReader::unreadChar(int): pos == 0."); + pos--; + if (pos < s.length()) + s[pos] = char(c); + } + + std::string getName() { + return __testlib_part(s); + } + + int getLine() { + return -1; + } + + bool eof() { + return pos >= s.length(); + } + + void close() { + // No operations. + } +}; + +class FileInputStreamReader : public InputStreamReader { +private: + std::FILE *file; + std::string name; + int line; + std::vector undoChars; + std::vector readChars; + std::vector undoReadChars; + + inline int postprocessGetc(int getcResult) { + if (getcResult != EOF) + return getcResult; + else + return EOFC; + } + + int getc(FILE *file) { + int c; + int rc; + + if (undoChars.empty()) { + c = rc = ::getc(file); + } else { + c = undoChars.back(); + undoChars.pop_back(); + rc = undoReadChars.back(); + undoReadChars.pop_back(); + } + + if (c == LF) + line++; + + readChars.push_back(rc); + return c; + } + + int ungetc(int c/*, FILE* file*/) { + if (!readChars.empty()) { + undoReadChars.push_back(readChars.back()); + readChars.pop_back(); + } + if (c == LF) + line--; + undoChars.push_back(c); + return c; + } + +public: + FileInputStreamReader(std::FILE *file, const std::string &name) : file(file), name(name), line(1) { + // No operations. + } + + void setTestCase(int testCase) { + if (testCase < 0 || testCase > __TESTLIB_MAX_TEST_CASE) + __testlib_fail(format("testCase expected fit in [1,%d], but %d doesn't", __TESTLIB_MAX_TEST_CASE, testCase)); + readChars.push_back(testCase + 256); + } + + std::vector getReadChars() { + return readChars; + } + + int curChar() { + if (feof(file)) + return EOFC; + else { + int c = getc(file); + ungetc(c/*, file*/); + return postprocessGetc(c); + } + } + + int nextChar() { + if (feof(file)) + return EOFC; + else + return postprocessGetc(getc(file)); + } + + void skipChar() { + getc(file); + } + + void unreadChar(int c) { + ungetc(c/*, file*/); + } + + std::string getName() { + return name; + } + + int getLine() { + return line; + } + + bool eof() { + if (NULL == file || feof(file)) + return true; + else { + int c = nextChar(); + if (c == EOFC || (c == EOF && feof(file))) + return true; + unreadChar(c); + return false; + } + } + + void close() { + if (NULL != file) { + fclose(file); + file = NULL; + } + } +}; + +class BufferedFileInputStreamReader : public InputStreamReader { +private: + static const size_t BUFFER_SIZE; + static const size_t MAX_UNREAD_COUNT; + + std::FILE *file; + std::string name; + int line; + + char *buffer; + bool *isEof; + int bufferPos; + size_t bufferSize; + + bool refill() { + if (NULL == file) + __testlib_fail("BufferedFileInputStreamReader: file == NULL (" + getName() + ")"); + + if (bufferPos >= int(bufferSize)) { + size_t readSize = fread( + buffer + MAX_UNREAD_COUNT, + 1, + BUFFER_SIZE - MAX_UNREAD_COUNT, + file + ); + + if (readSize < BUFFER_SIZE - MAX_UNREAD_COUNT + && ferror(file)) + __testlib_fail("BufferedFileInputStreamReader: unable to read (" + getName() + ")"); + + bufferSize = MAX_UNREAD_COUNT + readSize; + bufferPos = int(MAX_UNREAD_COUNT); + std::memset(isEof + MAX_UNREAD_COUNT, 0, sizeof(isEof[0]) * readSize); + + return readSize > 0; + } else + return true; + } + + char increment() { + char c; + if ((c = buffer[bufferPos++]) == LF) + line++; + return c; + } + +public: + BufferedFileInputStreamReader(std::FILE *file, const std::string &name) : file(file), name(name), line(1) { + buffer = new char[BUFFER_SIZE]; + isEof = new bool[BUFFER_SIZE]; + bufferSize = MAX_UNREAD_COUNT; + bufferPos = int(MAX_UNREAD_COUNT); + } + + ~BufferedFileInputStreamReader() { + if (NULL != buffer) { + delete[] buffer; + buffer = NULL; + } + if (NULL != isEof) { + delete[] isEof; + isEof = NULL; + } + } + + void setTestCase(int) { + __testlib_fail("setTestCase not implemented in BufferedFileInputStreamReader"); + } + + std::vector getReadChars() { + __testlib_fail("getReadChars not implemented in BufferedFileInputStreamReader"); + } + + int curChar() { + if (!refill()) + return EOFC; + + return isEof[bufferPos] ? EOFC : buffer[bufferPos]; + } + + int nextChar() { + if (!refill()) + return EOFC; + + return isEof[bufferPos] ? EOFC : increment(); + } + + void skipChar() { + increment(); + } + + void unreadChar(int c) { + bufferPos--; + if (bufferPos < 0) + __testlib_fail("BufferedFileInputStreamReader::unreadChar(int): bufferPos < 0"); + isEof[bufferPos] = (c == EOFC); + buffer[bufferPos] = char(c); + if (c == LF) + line--; + } + + std::string getName() { + return name; + } + + int getLine() { + return line; + } + + bool eof() { + return !refill() || EOFC == curChar(); + } + + void close() { + if (NULL != file) { + fclose(file); + file = NULL; + } + } +}; + +const size_t BufferedFileInputStreamReader::BUFFER_SIZE = 2000000; +const size_t BufferedFileInputStreamReader::MAX_UNREAD_COUNT = BufferedFileInputStreamReader::BUFFER_SIZE / 2; + +/* + * Streams to be used for reading data in checkers or validators. + * Each read*() method moves pointer to the next character after the + * read value. + */ +struct InStream { + /* Do not use them. */ + InStream(); + + ~InStream(); + + /* Wrap std::string with InStream. */ + InStream(const InStream &baseStream, std::string content); + + InputStreamReader *reader; + int lastLine; + + std::string name; + TMode mode; + bool opened; + bool stdfile; + bool strict; + + int wordReserveSize; + std::string _tmpReadToken; + + int readManyIteration; + size_t maxFileSize; + size_t maxTokenLength; + size_t maxMessageLength; + + void init(std::string fileName, TMode mode); + + void init(std::FILE *f, TMode mode); + + void setTestCase(int testCase); + std::vector getReadChars(); + + /* Moves stream pointer to the first non-white-space character or EOF. */ + void skipBlanks(); + + /* Returns current character in the stream. Doesn't remove it from stream. */ + char curChar(); + + /* Moves stream pointer one character forward. */ + void skipChar(); + + /* Returns current character and moves pointer one character forward. */ + char nextChar(); + + /* Returns current character and moves pointer one character forward. */ + char readChar(); + + /* As "readChar()" but ensures that the result is equal to given parameter. */ + char readChar(char c); + + /* As "readChar()" but ensures that the result is equal to the space (code=32). */ + char readSpace(); + + /* Puts back the character into the stream. */ + void unreadChar(char c); + + /* Reopens stream, you should not use it. */ + void reset(std::FILE *file = NULL); + + /* Checks that current position is EOF. If not it doesn't move stream pointer. */ + bool eof(); + + /* Moves pointer to the first non-white-space character and calls "eof()". */ + bool seekEof(); + + /* + * Checks that current position contains EOLN. + * If not it doesn't move stream pointer. + * In strict mode expects "#13#10" for windows or "#10" for other platforms. + */ + bool eoln(); + + /* Moves pointer to the first non-space and non-tab character and calls "eoln()". */ + bool seekEoln(); + + /* Moves stream pointer to the first character of the next line (if exists). */ + void nextLine(); + + /* + * Reads new token. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + std::string readWord(); + + /* The same as "readWord()", it is preffered to use "readToken()". */ + std::string readToken(); + + /* The same as "readWord()", but ensures that token matches to given pattern. */ + std::string readWord(const std::string &ptrn, const std::string &variableName = ""); + + std::string readWord(const pattern &p, const std::string &variableName = ""); + + std::vector + readWords(int size, const std::string &ptrn, const std::string &variablesName = "", int indexBase = 1); + + std::vector + readWords(int size, const pattern &p, const std::string &variablesName = "", int indexBase = 1); + + std::vector readWords(int size, int indexBase = 1); + + /* The same as "readToken()", but ensures that token matches to given pattern. */ + std::string readToken(const std::string &ptrn, const std::string &variableName = ""); + + std::string readToken(const pattern &p, const std::string &variableName = ""); + + std::vector + readTokens(int size, const std::string &ptrn, const std::string &variablesName = "", int indexBase = 1); + + std::vector + readTokens(int size, const pattern &p, const std::string &variablesName = "", int indexBase = 1); + + std::vector readTokens(int size, int indexBase = 1); + + void readWordTo(std::string &result); + + void readWordTo(std::string &result, const pattern &p, const std::string &variableName = ""); + + void readWordTo(std::string &result, const std::string &ptrn, const std::string &variableName = ""); + + void readTokenTo(std::string &result); + + void readTokenTo(std::string &result, const pattern &p, const std::string &variableName = ""); + + void readTokenTo(std::string &result, const std::string &ptrn, const std::string &variableName = ""); + + /* + * Reads new long long value. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + long long readLong(); + + unsigned long long readUnsignedLong(); + + /* + * Reads new int. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + int readInteger(); + + /* + * Reads new int. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + int readInt(); + + /* As "readLong()" but ensures that value in the range [minv,maxv]. */ + long long readLong(long long minv, long long maxv, const std::string &variableName = ""); + + /* Reads space-separated sequence of long longs. */ + std::vector + readLongs(int size, long long minv, long long maxv, const std::string &variablesName = "", int indexBase = 1); + + /* Reads space-separated sequence of long longs. */ + std::vector readLongs(int size, int indexBase = 1); + + unsigned long long + readUnsignedLong(unsigned long long minv, unsigned long long maxv, const std::string &variableName = ""); + + std::vector + readUnsignedLongs(int size, unsigned long long minv, unsigned long long maxv, const std::string &variablesName = "", + int indexBase = 1); + + std::vector readUnsignedLongs(int size, int indexBase = 1); + + unsigned long long readLong(unsigned long long minv, unsigned long long maxv, const std::string &variableName = ""); + + std::vector + readLongs(int size, unsigned long long minv, unsigned long long maxv, const std::string &variablesName = "", + int indexBase = 1); + + /* As "readInteger()" but ensures that value in the range [minv,maxv]. */ + int readInteger(int minv, int maxv, const std::string &variableName = ""); + + /* As "readInt()" but ensures that value in the range [minv,maxv]. */ + int readInt(int minv, int maxv, const std::string &variableName = ""); + + /* Reads space-separated sequence of integers. */ + std::vector + readIntegers(int size, int minv, int maxv, const std::string &variablesName = "", int indexBase = 1); + + /* Reads space-separated sequence of integers. */ + std::vector readIntegers(int size, int indexBase = 1); + + /* Reads space-separated sequence of integers. */ + std::vector readInts(int size, int minv, int maxv, const std::string &variablesName = "", int indexBase = 1); + + /* Reads space-separated sequence of integers. */ + std::vector readInts(int size, int indexBase = 1); + + /* + * Reads new double. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + double readReal(); + + /* + * Reads new double. Ignores white-spaces into the non-strict mode + * (strict mode is used in validators usually). + */ + double readDouble(); + + /* As "readReal()" but ensures that value in the range [minv,maxv]. */ + double readReal(double minv, double maxv, const std::string &variableName = ""); + + std::vector + readReals(int size, double minv, double maxv, const std::string &variablesName = "", int indexBase = 1); + + std::vector readReals(int size, int indexBase = 1); + + /* As "readDouble()" but ensures that value in the range [minv,maxv]. */ + double readDouble(double minv, double maxv, const std::string &variableName = ""); + + std::vector + readDoubles(int size, double minv, double maxv, const std::string &variablesName = "", int indexBase = 1); + + std::vector readDoubles(int size, int indexBase = 1); + + /* + * As "readReal()" but ensures that value in the range [minv,maxv] and + * number of digit after the decimal point is in range [minAfterPointDigitCount,maxAfterPointDigitCount] + * and number is in the form "[-]digit(s)[.digit(s)]". + */ + double readStrictReal(double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variableName = ""); + + std::vector readStrictReals(int size, double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variablesName = "", int indexBase = 1); + + /* + * As "readDouble()" but ensures that value in the range [minv,maxv] and + * number of digit after the decimal point is in range [minAfterPointDigitCount,maxAfterPointDigitCount] + * and number is in the form "[-]digit(s)[.digit(s)]". + */ + double readStrictDouble(double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variableName = ""); + + std::vector readStrictDoubles(int size, double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variablesName = "", int indexBase = 1); + + /* As readLine(). */ + std::string readString(); + + /* Read many lines. */ + std::vector readStrings(int size, int indexBase = 1); + + /* See readLine(). */ + void readStringTo(std::string &result); + + /* The same as "readLine()/readString()", but ensures that line matches to the given pattern. */ + std::string readString(const pattern &p, const std::string &variableName = ""); + + /* The same as "readLine()/readString()", but ensures that line matches to the given pattern. */ + std::string readString(const std::string &ptrn, const std::string &variableName = ""); + + /* Read many lines. */ + std::vector + readStrings(int size, const pattern &p, const std::string &variableName = "", int indexBase = 1); + + /* Read many lines. */ + std::vector + readStrings(int size, const std::string &ptrn, const std::string &variableName = "", int indexBase = 1); + + /* The same as "readLine()/readString()", but ensures that line matches to the given pattern. */ + void readStringTo(std::string &result, const pattern &p, const std::string &variableName = ""); + + /* The same as "readLine()/readString()", but ensures that line matches to the given pattern. */ + void readStringTo(std::string &result, const std::string &ptrn, const std::string &variableName = ""); + + /* + * Reads line from the current position to EOLN or EOF. Moves stream pointer to + * the first character of the new line (if possible). + */ + std::string readLine(); + + /* Read many lines. */ + std::vector readLines(int size, int indexBase = 1); + + /* See readLine(). */ + void readLineTo(std::string &result); + + /* The same as "readLine()", but ensures that line matches to the given pattern. */ + std::string readLine(const pattern &p, const std::string &variableName = ""); + + /* The same as "readLine()", but ensures that line matches to the given pattern. */ + std::string readLine(const std::string &ptrn, const std::string &variableName = ""); + + /* Read many lines. */ + std::vector + readLines(int size, const pattern &p, const std::string &variableName = "", int indexBase = 1); + + /* Read many lines. */ + std::vector + readLines(int size, const std::string &ptrn, const std::string &variableName = "", int indexBase = 1); + + /* The same as "readLine()", but ensures that line matches to the given pattern. */ + void readLineTo(std::string &result, const pattern &p, const std::string &variableName = ""); + + /* The same as "readLine()", but ensures that line matches to the given pattern. */ + void readLineTo(std::string &result, const std::string &ptrn, const std::string &variableName = ""); + + /* Reads EOLN or fails. Use it in validators. Calls "eoln()" method internally. */ + void readEoln(); + + /* Reads EOF or fails. Use it in validators. Calls "eof()" method internally. */ + void readEof(); + + /* + * Quit-functions aborts program with and : + * input/answer streams replace any result to FAIL. + */ + NORETURN void quit(TResult result, const char *msg); + /* + * Quit-functions aborts program with and : + * input/answer streams replace any result to FAIL. + */ + NORETURN void quitf(TResult result, const char *msg, ...); + + /* + * Quit-functions aborts program with and : + * input/answer streams replace any result to FAIL. + */ + void quitif(bool condition, TResult result, const char *msg, ...); + /* + * Quit-functions aborts program with and : + * input/answer streams replace any result to FAIL. + */ + NORETURN void quits(TResult result, std::string msg); + + /* + * Checks condition and aborts a program if codition is false. + * Returns _wa for ouf and _fail on any other streams. + */ +#ifdef __GNUC__ + __attribute__ ((format (printf, 3, 4))) +#endif + void ensuref(bool cond, const char *format, ...); + + void __testlib_ensure(bool cond, std::string message); + + void close(); + + const static int NO_INDEX = INT_MAX; + const static char OPEN_BRACKET = char(11); + const static char CLOSE_BRACKET = char(17); + + const static WORD LightGray = 0x07; + const static WORD LightRed = 0x0c; + const static WORD LightCyan = 0x0b; + const static WORD LightGreen = 0x0a; + const static WORD LightYellow = 0x0e; + + static void textColor(WORD color); + + static void quitscr(WORD color, const char *msg); + + static void quitscrS(WORD color, std::string msg); + + void xmlSafeWrite(std::FILE *file, const char *msg); + + /* Skips UTF-8 Byte Order Mark. */ + void skipBom(); + +private: + InStream(const InStream &); + + InStream &operator=(const InStream &); +}; + +InStream inf; +InStream ouf; +InStream ans; +bool appesMode; +std::string resultName; +std::string checkerName = "untitled checker"; +random_t rnd; +TTestlibMode testlibMode = _unknown; +double __testlib_points = std::numeric_limits::infinity(); + +struct ValidatorBoundsHit { + static const double EPS; + bool minHit; + bool maxHit; + + ValidatorBoundsHit(bool minHit = false, bool maxHit = false) : minHit(minHit), maxHit(maxHit) { + }; + + ValidatorBoundsHit merge(const ValidatorBoundsHit &validatorBoundsHit) { + return ValidatorBoundsHit( + __testlib_max(minHit, validatorBoundsHit.minHit), + __testlib_max(maxHit, validatorBoundsHit.maxHit) + ); + } +}; + +const double ValidatorBoundsHit::EPS = 1E-12; + +class Validator { +private: + const static std::string TEST_MARKUP_HEADER; + const static std::string TEST_CASE_OPEN_TAG; + const static std::string TEST_CASE_CLOSE_TAG; + + bool _initialized; + std::string _testset; + std::string _group; + + std::string _testOverviewLogFileName; + std::string _testMarkupFileName; + int _testCase = -1; + std::string _testCaseFileName; + + std::map _boundsHitByVariableName; + std::set _features; + std::set _hitFeatures; + + bool isVariableNameBoundsAnalyzable(const std::string &variableName) { + for (size_t i = 0; i < variableName.length(); i++) + if ((variableName[i] >= '0' && variableName[i] <= '9') || variableName[i] < ' ') + return false; + return true; + } + + bool isFeatureNameAnalyzable(const std::string &featureName) { + for (size_t i = 0; i < featureName.length(); i++) + if (featureName[i] < ' ') + return false; + return true; + } + +public: + Validator() : _initialized(false), _testset("tests"), _group() { + } + + void initialize() { + _initialized = true; + } + + std::string testset() const { + if (!_initialized) + __testlib_fail("Validator should be initialized with registerValidation(argc, argv) instead of registerValidation() to support validator.testset()"); + return _testset; + } + + std::string group() const { + if (!_initialized) + __testlib_fail("Validator should be initialized with registerValidation(argc, argv) instead of registerValidation() to support validator.group()"); + return _group; + } + + std::string testOverviewLogFileName() const { + return _testOverviewLogFileName; + } + + std::string testMarkupFileName() const { + return _testMarkupFileName; + } + + int testCase() const { + return _testCase; + } + + std::string testCaseFileName() const { + return _testCaseFileName; + } + + void setTestset(const char *const testset) { + _testset = testset; + } + + void setGroup(const char *const group) { + _group = group; + } + + void setTestOverviewLogFileName(const char *const testOverviewLogFileName) { + _testOverviewLogFileName = testOverviewLogFileName; + } + + void setTestMarkupFileName(const char *const testMarkupFileName) { + _testMarkupFileName = testMarkupFileName; + } + + void setTestCase(int testCase) { + _testCase = testCase; + } + + void setTestCaseFileName(const char *const testCaseFileName) { + _testCaseFileName = testCaseFileName; + } + + void addBoundsHit(const std::string &variableName, ValidatorBoundsHit boundsHit) { + if (isVariableNameBoundsAnalyzable(variableName)) { + _boundsHitByVariableName[variableName] + = boundsHit.merge(_boundsHitByVariableName[variableName]); + } + } + + std::string getBoundsHitLog() { + std::string result; + for (std::map::iterator i = _boundsHitByVariableName.begin(); + i != _boundsHitByVariableName.end(); + i++) { + result += "\"" + i->first + "\":"; + if (i->second.minHit) + result += " min-value-hit"; + if (i->second.maxHit) + result += " max-value-hit"; + result += "\n"; + } + return result; + } + + std::string getFeaturesLog() { + std::string result; + for (std::set::iterator i = _features.begin(); + i != _features.end(); + i++) { + result += "feature \"" + *i + "\":"; + if (_hitFeatures.count(*i)) + result += " hit"; + result += "\n"; + } + return result; + } + + void writeTestOverviewLog() { + if (!_testOverviewLogFileName.empty()) { + std::string fileName(_testOverviewLogFileName); + _testOverviewLogFileName = ""; + FILE *testOverviewLogFile = fopen(fileName.c_str(), "w"); + if (NULL == testOverviewLogFile) + __testlib_fail("Validator::writeTestOverviewLog: can't write test overview log to (" + fileName + ")"); + fprintf(testOverviewLogFile, "%s%s", getBoundsHitLog().c_str(), getFeaturesLog().c_str()); + if (fclose(testOverviewLogFile)) + __testlib_fail( + "Validator::writeTestOverviewLog: can't close test overview log file (" + fileName + ")"); + } + } + + void writeTestMarkup() { + if (!_testMarkupFileName.empty()) { + std::vector readChars = inf.getReadChars(); + if (!readChars.empty()) { + std::string markup(TEST_MARKUP_HEADER); + for (size_t i = 0; i < readChars.size(); i++) { + int c = readChars[i]; + if (i + 1 == readChars.size() && c == -1) + continue; + if (c <= 256) { + char cc = char(c); + if (cc == '\\' || cc == '!') + markup += '\\'; + markup += cc; + } else { + markup += TEST_CASE_OPEN_TAG; + markup += toString(c - 256); + markup += TEST_CASE_CLOSE_TAG; + } + } + FILE* f; + bool standard_file = false; + if (_testMarkupFileName == "stdout") + f = stdout, standard_file = true; + else if (_testMarkupFileName == "stderr") + f = stderr, standard_file = true; + else { + f = fopen(_testMarkupFileName.c_str(), "wb"); + if (NULL == f) + __testlib_fail("Validator::writeTestMarkup: can't write test markup to (" + _testMarkupFileName + ")"); + } + std::fprintf(f, "%s", markup.c_str()); + std::fflush(f); + if (!standard_file) + if (std::fclose(f)) + __testlib_fail("Validator::writeTestMarkup: can't close test markup file (" + _testCaseFileName + ")"); + } + } + } + + void writeTestCase() { + if (_testCase > 0) { + std::vector readChars = inf.getReadChars(); + if (!readChars.empty()) { + std::string content, testCaseContent; + bool matchedTestCase = false; + for (size_t i = 0; i < readChars.size(); i++) { + int c = readChars[i]; + if (i + 1 == readChars.size() && c == -1) + continue; + if (c <= 256) + content += char(c); + else { + if (matchedTestCase) { + testCaseContent = content; + matchedTestCase = false; + } + content = ""; + int testCase = c - 256; + if (testCase == _testCase) + matchedTestCase = true; + } + } + if (matchedTestCase) + testCaseContent = content; + + if (!testCaseContent.empty()) { + FILE* f; + bool standard_file = false; + if (_testCaseFileName.empty() || _testCaseFileName == "stdout") + f = stdout, standard_file = true; + else if (_testCaseFileName == "stderr") + f = stderr, standard_file = true; + else { + f = fopen(_testCaseFileName.c_str(), "wb"); + if (NULL == f) + __testlib_fail("Validator::writeTestCase: can't write test case to (" + _testCaseFileName + ")"); + } + std::fprintf(f, "%s", testCaseContent.c_str()); + std::fflush(f); + if (!standard_file) + if (std::fclose(f)) + __testlib_fail("Validator::writeTestCase: can't close test case file (" + _testCaseFileName + ")"); + } + } + } + } + + void addFeature(const std::string &feature) { + if (_features.count(feature)) + __testlib_fail("Feature " + feature + " registered twice."); + if (!isFeatureNameAnalyzable(feature)) + __testlib_fail("Feature name '" + feature + "' contains restricted characters."); + + _features.insert(feature); + } + + void feature(const std::string &feature) { + if (!isFeatureNameAnalyzable(feature)) + __testlib_fail("Feature name '" + feature + "' contains restricted characters."); + + if (!_features.count(feature)) + __testlib_fail("Feature " + feature + " didn't registered via addFeature(feature)."); + + _hitFeatures.insert(feature); + } +} validator; + +const std::string Validator::TEST_MARKUP_HEADER = "MU\xF3\x01"; +const std::string Validator::TEST_CASE_OPEN_TAG = "!c"; +const std::string Validator::TEST_CASE_CLOSE_TAG = ";"; + +struct TestlibFinalizeGuard { + static bool alive; + static bool registered; + + int quitCount, readEofCount; + + TestlibFinalizeGuard() : quitCount(0), readEofCount(0) { + // No operations. + } + + ~TestlibFinalizeGuard() { + bool _alive = alive; + alive = false; + + if (_alive) { + if (testlibMode == _checker && quitCount == 0) + __testlib_fail("Checker must end with quit or quitf call."); + + if (testlibMode == _validator && readEofCount == 0 && quitCount == 0) + __testlib_fail("Validator must end with readEof call."); + + /* opts */ + autoEnsureNoUnusedOpts(); + + if (!registered) + __testlib_fail("Call register-function in the first line of the main (registerTestlibCmd or other similar)"); + } + + if (__testlib_exitCode == 0) { + validator.writeTestOverviewLog(); + validator.writeTestMarkup(); + validator.writeTestCase(); + } + } + +private: + /* opts */ + void autoEnsureNoUnusedOpts(); +}; + +bool TestlibFinalizeGuard::alive = true; +bool TestlibFinalizeGuard::registered = false; +extern TestlibFinalizeGuard testlibFinalizeGuard; + +/* + * Call it to disable checks on finalization. + */ +void disableFinalizeGuard() { + TestlibFinalizeGuard::alive = false; +} + +/* Interactor streams. + */ +std::fstream tout; + +/* implementation + */ + +InStream::InStream() { + reader = NULL; + lastLine = -1; + opened = false; + name = ""; + mode = _input; + strict = false; + stdfile = false; + wordReserveSize = 4; + readManyIteration = NO_INDEX; + maxFileSize = 128 * 1024 * 1024; // 128MB. + maxTokenLength = 32 * 1024 * 1024; // 32MB. + maxMessageLength = 32000; +} + +InStream::InStream(const InStream &baseStream, std::string content) { + reader = new StringInputStreamReader(content); + lastLine = -1; + opened = true; + strict = baseStream.strict; + stdfile = false; + mode = baseStream.mode; + name = "based on " + baseStream.name; + readManyIteration = NO_INDEX; + maxFileSize = 128 * 1024 * 1024; // 128MB. + maxTokenLength = 32 * 1024 * 1024; // 32MB. + maxMessageLength = 32000; +} + +InStream::~InStream() { + if (NULL != reader) { + reader->close(); + delete reader; + reader = NULL; + } +} + +void InStream::setTestCase(int testCase) { + if (testlibMode != _validator || mode != _input || !stdfile || this != &inf) + __testlib_fail("InStream::setTestCase can be used only for inf in validator-mode." + " Actually, prefer setTestCase function instead of InStream member"); + reader->setTestCase(testCase); +} + +std::vector InStream::getReadChars() { + if (testlibMode != _validator || mode != _input || !stdfile || this != &inf) + __testlib_fail("InStream::getReadChars can be used only for inf in validator-mode."); + return reader == NULL ? std::vector() : reader->getReadChars(); +} + +void setTestCase(int testCase) { + static bool first_run = true; + static bool zero_based = false; + + if (first_run && testCase == 0) + zero_based = true; + + if (zero_based) + testCase++; + + __testlib_hasTestCase = true; + __testlib_testCase = testCase; + + if (testlibMode == _validator) + inf.setTestCase(testCase); + + first_run = false; +} + +#ifdef __GNUC__ +__attribute__((const)) +#endif +int resultExitCode(TResult r) { + if (r == _ok) + return OK_EXIT_CODE; + if (r == _wa) + return WA_EXIT_CODE; + if (r == _pe) + return PE_EXIT_CODE; + if (r == _fail) + return FAIL_EXIT_CODE; + if (r == _dirt) + return DIRT_EXIT_CODE; + if (r == _points) + return POINTS_EXIT_CODE; + if (r == _unexpected_eof) +#ifdef ENABLE_UNEXPECTED_EOF + return UNEXPECTED_EOF_EXIT_CODE; +#else + return PE_EXIT_CODE; +#endif + if (r >= _partially) + return PC_BASE_EXIT_CODE + (r - _partially); + return FAIL_EXIT_CODE; +} + +void InStream::textColor( +#if !(defined(ON_WINDOWS) && (!defined(_MSC_VER) || _MSC_VER > 1400)) && defined(__GNUC__) + __attribute__((unused)) +#endif + WORD color +) { +#if defined(ON_WINDOWS) && (!defined(_MSC_VER) || _MSC_VER > 1400) + HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(handle, color); +#endif +#if !defined(ON_WINDOWS) && defined(__GNUC__) + if (isatty(2)) + { + switch (color) + { + case LightRed: + fprintf(stderr, "\033[1;31m"); + break; + case LightCyan: + fprintf(stderr, "\033[1;36m"); + break; + case LightGreen: + fprintf(stderr, "\033[1;32m"); + break; + case LightYellow: + fprintf(stderr, "\033[1;33m"); + break; + case LightGray: + default: + fprintf(stderr, "\033[0m"); + } + } +#endif +} + +#ifdef TESTLIB_THROW_EXIT_EXCEPTION_INSTEAD_OF_EXIT +class exit_exception: public std::exception { +private: + int exitCode; +public: + exit_exception(int exitCode): exitCode(exitCode) {} + int getExitCode() { return exitCode; } +}; +#endif + +NORETURN void halt(int exitCode) { +#ifdef FOOTER + InStream::textColor(InStream::LightGray); + std::fprintf(stderr, "Checker: \"%s\"\n", checkerName.c_str()); + std::fprintf(stderr, "Exit code: %d\n", exitCode); + InStream::textColor(InStream::LightGray); +#endif + __testlib_exitCode = exitCode; +#ifdef TESTLIB_THROW_EXIT_EXCEPTION_INSTEAD_OF_EXIT + throw exit_exception(exitCode); +#endif + std::exit(exitCode); +} + +static bool __testlib_shouldCheckDirt(TResult result) { + return result == _ok || result == _points || result >= _partially; +} + +static std::string __testlib_appendMessage(const std::string &message, const std::string &extra) { + int openPos = -1, closePos = -1; + for (size_t i = 0; i < message.length(); i++) { + if (message[i] == InStream::OPEN_BRACKET) { + if (openPos == -1) + openPos = int(i); + else + openPos = INT_MAX; + } + if (message[i] == InStream::CLOSE_BRACKET) { + if (closePos == -1) + closePos = int(i); + else + closePos = INT_MAX; + } + } + if (openPos != -1 && openPos != INT_MAX + && closePos != -1 && closePos != INT_MAX + && openPos < closePos) { + size_t index = message.find(extra, openPos); + if (index == std::string::npos || int(index) >= closePos) { + std::string result(message); + result.insert(closePos, ", " + extra); + return result; + } + return message; + } + + return message + " " + InStream::OPEN_BRACKET + extra + InStream::CLOSE_BRACKET; +} + +static std::string __testlib_toPrintableMessage(const std::string &message) { + int openPos = -1, closePos = -1; + for (size_t i = 0; i < message.length(); i++) { + if (message[i] == InStream::OPEN_BRACKET) { + if (openPos == -1) + openPos = int(i); + else + openPos = INT_MAX; + } + if (message[i] == InStream::CLOSE_BRACKET) { + if (closePos == -1) + closePos = int(i); + else + closePos = INT_MAX; + } + } + if (openPos != -1 && openPos != INT_MAX + && closePos != -1 && closePos != INT_MAX + && openPos < closePos) { + std::string result(message); + result[openPos] = '('; + result[closePos] = ')'; + return result; + } + + return message; +} + +NORETURN void InStream::quit(TResult result, const char *msg) { + if (TestlibFinalizeGuard::alive) + testlibFinalizeGuard.quitCount++; + + std::string message(msg); + message = trim(message); + + if (__testlib_hasTestCase) { + if (result != _ok) + message = __testlib_appendMessage(message, "test case " + vtos(__testlib_testCase)); + else { + if (__testlib_testCase == 1) + message = __testlib_appendMessage(message, vtos(__testlib_testCase) + " test case"); + else + message = __testlib_appendMessage(message, vtos(__testlib_testCase) + " test cases"); + } + } + + // You can change maxMessageLength. + // Example: 'inf.maxMessageLength = 1024 * 1024;'. + if (message.length() > maxMessageLength) { + std::string warn = "message length exceeds " + vtos(maxMessageLength) + + ", the message is truncated: "; + message = warn + message.substr(0, maxMessageLength - warn.length()); + } + +#ifndef ENABLE_UNEXPECTED_EOF + if (result == _unexpected_eof) + result = _pe; +#endif + + if (testlibMode == _scorer && result != _fail) + quits(_fail, "Scorer should return points only. Don't use a quit function."); + + if (mode != _output && result != _fail) { + if (mode == _input && testlibMode == _validator && lastLine != -1) + quits(_fail, __testlib_appendMessage(__testlib_appendMessage(message, name), "line " + vtos(lastLine))); + else + quits(_fail, __testlib_appendMessage(message, name)); + } + + std::FILE *resultFile; + std::string errorName; + + if (__testlib_shouldCheckDirt(result)) { + if (testlibMode != _interactor && !ouf.seekEof()) + quit(_dirt, "Extra information in the output file"); + } + + int pctype = result - _partially; + bool isPartial = false; + + switch (result) { + case _ok: + errorName = "ok "; + quitscrS(LightGreen, errorName); + break; + case _wa: + errorName = "wrong answer "; + quitscrS(LightRed, errorName); + break; + case _pe: + errorName = "wrong output format "; + quitscrS(LightRed, errorName); + break; + case _fail: + errorName = "FAIL "; + quitscrS(LightRed, errorName); + break; + case _dirt: + errorName = "wrong output format "; + quitscrS(LightCyan, errorName); + result = _pe; + break; + case _points: + errorName = "points "; + quitscrS(LightYellow, errorName); + break; + case _unexpected_eof: + errorName = "unexpected eof "; + quitscrS(LightCyan, errorName); + break; + default: + if (result >= _partially) { + errorName = format("partially correct (%d) ", pctype); + isPartial = true; + quitscrS(LightYellow, errorName); + } else + quit(_fail, "What is the code ??? "); + } + + if (resultName != "") { + resultFile = std::fopen(resultName.c_str(), "w"); + if (resultFile == NULL) { + resultName = ""; + quit(_fail, "Can not write to the result file"); + } + if (appesMode) { + std::fprintf(resultFile, ""); + if (isPartial) + std::fprintf(resultFile, "", + outcomes[(int) _partially].c_str(), pctype); + else { + if (result != _points) + std::fprintf(resultFile, "", outcomes[(int) result].c_str()); + else { + if (__testlib_points == std::numeric_limits::infinity()) + quit(_fail, "Expected points, but infinity found"); + std::string stringPoints = removeDoubleTrailingZeroes(format("%.10f", __testlib_points)); + std::fprintf(resultFile, "", + outcomes[(int) result].c_str(), stringPoints.c_str()); + } + } + xmlSafeWrite(resultFile, __testlib_toPrintableMessage(message).c_str()); + std::fprintf(resultFile, "\n"); + } else + std::fprintf(resultFile, "%s", __testlib_toPrintableMessage(message).c_str()); + if (NULL == resultFile || fclose(resultFile) != 0) { + resultName = ""; + quit(_fail, "Can not write to the result file"); + } + } + + quitscr(LightGray, __testlib_toPrintableMessage(message).c_str()); + std::fprintf(stderr, "\n"); + + inf.close(); + ouf.close(); + ans.close(); + if (tout.is_open()) + tout.close(); + + textColor(LightGray); + + if (resultName != "") + std::fprintf(stderr, "See file to check exit message\n"); + + halt(resultExitCode(result)); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 4))) +#endif +NORETURN void InStream::quitf(TResult result, const char *msg, ...) { + FMT_TO_RESULT(msg, msg, message); + InStream::quit(result, message.c_str()); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +void InStream::quitif(bool condition, TResult result, const char *msg, ...) { + if (condition) { + FMT_TO_RESULT(msg, msg, message); + InStream::quit(result, message.c_str()); + } +} + +NORETURN void InStream::quits(TResult result, std::string msg) { + InStream::quit(result, msg.c_str()); +} + +void InStream::xmlSafeWrite(std::FILE *file, const char *msg) { + size_t lmsg = strlen(msg); + for (size_t i = 0; i < lmsg; i++) { + if (msg[i] == '&') { + std::fprintf(file, "%s", "&"); + continue; + } + if (msg[i] == '<') { + std::fprintf(file, "%s", "<"); + continue; + } + if (msg[i] == '>') { + std::fprintf(file, "%s", ">"); + continue; + } + if (msg[i] == '"') { + std::fprintf(file, "%s", """); + continue; + } + if (0 <= msg[i] && msg[i] <= 31) { + std::fprintf(file, "%c", '.'); + continue; + } + std::fprintf(file, "%c", msg[i]); + } +} + +void InStream::quitscrS(WORD color, std::string msg) { + quitscr(color, msg.c_str()); +} + +void InStream::quitscr(WORD color, const char *msg) { + if (resultName == "") { + textColor(color); + std::fprintf(stderr, "%s", msg); + textColor(LightGray); + } +} + +void InStream::reset(std::FILE *file) { + if (opened && stdfile) + quit(_fail, "Can't reset standard handle"); + + if (opened) + close(); + + if (!stdfile && NULL == file) + if (NULL == (file = std::fopen(name.c_str(), "rb"))) { + if (mode == _output) + quits(_pe, std::string("Output file not found: \"") + name + "\""); + + if (mode == _answer) + quits(_fail, std::string("Answer file not found: \"") + name + "\""); + } + + if (NULL != file) { + opened = true; + __testlib_set_binary(file); + + if (stdfile) + reader = new FileInputStreamReader(file, name); + else + reader = new BufferedFileInputStreamReader(file, name); + } else { + opened = false; + reader = NULL; + } +} + +void InStream::init(std::string fileName, TMode mode) { + opened = false; + name = fileName; + stdfile = false; + this->mode = mode; + + std::ifstream stream; + stream.open(fileName.c_str(), std::ios::in); + if (stream.is_open()) { + std::streampos start = stream.tellg(); + stream.seekg(0, std::ios::end); + std::streampos end = stream.tellg(); + size_t fileSize = size_t(end - start); + stream.close(); + + // You can change maxFileSize. + // Example: 'inf.maxFileSize = 256 * 1024 * 1024;'. + if (fileSize > maxFileSize) + quitf(_pe, "File size exceeds %d bytes, size is %d", int(maxFileSize), int(fileSize)); + } + + reset(); + skipBom(); +} + +void InStream::init(std::FILE *f, TMode mode) { + opened = false; + name = "untitled"; + this->mode = mode; + + if (f == stdin) + name = "stdin", stdfile = true; + if (f == stdout) + name = "stdout", stdfile = true; + if (f == stderr) + name = "stderr", stdfile = true; + + reset(f); + skipBom(); +} + +void InStream::skipBom() { + const std::string utf8Bom = "\xEF\xBB\xBF"; + size_t index = 0; + while (index < utf8Bom.size() && curChar() == utf8Bom[index]) { + index++; + skipChar(); + } + if (index < utf8Bom.size()) { + while (index != 0) { + unreadChar(utf8Bom[index - 1]); + index--; + } + } +} + +char InStream::curChar() { + return char(reader->curChar()); +} + +char InStream::nextChar() { + return char(reader->nextChar()); +} + +char InStream::readChar() { + return nextChar(); +} + +char InStream::readChar(char c) { + lastLine = reader->getLine(); + char found = readChar(); + if (c != found) { + if (!isEoln(found)) + quit(_pe, ("Unexpected character '" + std::string(1, found) + "', but '" + std::string(1, c) + + "' expected").c_str()); + else + quit(_pe, ("Unexpected character " + ("#" + vtos(int(found))) + ", but '" + std::string(1, c) + + "' expected").c_str()); + } + return found; +} + +char InStream::readSpace() { + return readChar(' '); +} + +void InStream::unreadChar(char c) { + reader->unreadChar(c); +} + +void InStream::skipChar() { + reader->skipChar(); +} + +void InStream::skipBlanks() { + while (isBlanks(reader->curChar())) + reader->skipChar(); +} + +std::string InStream::readWord() { + readWordTo(_tmpReadToken); + return _tmpReadToken; +} + +void InStream::readWordTo(std::string &result) { + if (!strict) + skipBlanks(); + + lastLine = reader->getLine(); + int cur = reader->nextChar(); + + if (cur == EOFC) + quit(_unexpected_eof, "Unexpected end of file - token expected"); + + if (isBlanks(cur)) + quit(_pe, "Unexpected white-space - token expected"); + + result.clear(); + + while (!(isBlanks(cur) || cur == EOFC)) { + result += char(cur); + + // You can change maxTokenLength. + // Example: 'inf.maxTokenLength = 128 * 1024 * 1024;'. + if (result.length() > maxTokenLength) + quitf(_pe, "Length of token exceeds %d, token is '%s...'", int(maxTokenLength), + __testlib_part(result).c_str()); + + cur = reader->nextChar(); + } + + reader->unreadChar(cur); + + if (result.length() == 0) + quit(_unexpected_eof, "Unexpected end of file or white-space - token expected"); +} + +std::string InStream::readToken() { + return readWord(); +} + +void InStream::readTokenTo(std::string &result) { + readWordTo(result); +} + +static std::string __testlib_part(const std::string &s) { + std::string t; + for (size_t i = 0; i < s.length(); i++) + if (s[i] != '\0') + t += s[i]; + else + t += '~'; + if (t.length() <= 64) + return t; + else + return t.substr(0, 30) + "..." + t.substr(s.length() - 31, 31); +} + +#define __testlib_readMany(readMany, readOne, typeName, space) \ + if (size < 0) \ + quit(_fail, #readMany ": size should be non-negative."); \ + if (size > 100000000) \ + quit(_fail, #readMany ": size should be at most 100000000."); \ + \ + std::vector result(size); \ + readManyIteration = indexBase; \ + \ + for (int i = 0; i < size; i++) \ + { \ + result[i] = readOne; \ + readManyIteration++; \ + if (strict && space && i + 1 < size) \ + readSpace(); \ + } \ + \ + readManyIteration = NO_INDEX; \ + return result; \ + + +std::string InStream::readWord(const pattern &p, const std::string &variableName) { + readWordTo(_tmpReadToken); + if (!p.matches(_tmpReadToken)) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, + ("Token \"" + __testlib_part(_tmpReadToken) + "\" doesn't correspond to pattern \"" + p.src() + + "\"").c_str()); + else + quit(_wa, ("Token parameter [name=" + variableName + "] equals to \"" + __testlib_part(_tmpReadToken) + + "\", doesn't correspond to pattern \"" + p.src() + "\"").c_str()); + } else { + if (variableName.empty()) + quit(_wa, ("Token element [index=" + vtos(readManyIteration) + "] equals to \"" + + __testlib_part(_tmpReadToken) + "\" doesn't correspond to pattern \"" + p.src() + + "\"").c_str()); + else + quit(_wa, ("Token element " + variableName + "[" + vtos(readManyIteration) + "] equals to \"" + + __testlib_part(_tmpReadToken) + "\", doesn't correspond to pattern \"" + p.src() + + "\"").c_str()); + } + } + return _tmpReadToken; +} + +std::vector +InStream::readWords(int size, const pattern &p, const std::string &variablesName, int indexBase) { + __testlib_readMany(readWords, readWord(p, variablesName), std::string, true); +} + +std::vector InStream::readWords(int size, int indexBase) { + __testlib_readMany(readWords, readWord(), std::string, true); +} + +std::string InStream::readWord(const std::string &ptrn, const std::string &variableName) { + return readWord(pattern(ptrn), variableName); +} + +std::vector +InStream::readWords(int size, const std::string &ptrn, const std::string &variablesName, int indexBase) { + pattern p(ptrn); + __testlib_readMany(readWords, readWord(p, variablesName), std::string, true); +} + +std::string InStream::readToken(const pattern &p, const std::string &variableName) { + return readWord(p, variableName); +} + +std::vector +InStream::readTokens(int size, const pattern &p, const std::string &variablesName, int indexBase) { + __testlib_readMany(readTokens, readToken(p, variablesName), std::string, true); +} + +std::vector InStream::readTokens(int size, int indexBase) { + __testlib_readMany(readTokens, readToken(), std::string, true); +} + +std::string InStream::readToken(const std::string &ptrn, const std::string &variableName) { + return readWord(ptrn, variableName); +} + +std::vector +InStream::readTokens(int size, const std::string &ptrn, const std::string &variablesName, int indexBase) { + pattern p(ptrn); + __testlib_readMany(readTokens, readWord(p, variablesName), std::string, true); +} + +void InStream::readWordTo(std::string &result, const pattern &p, const std::string &variableName) { + readWordTo(result); + if (!p.matches(result)) { + if (variableName.empty()) + quit(_wa, ("Token \"" + __testlib_part(result) + "\" doesn't correspond to pattern \"" + p.src() + + "\"").c_str()); + else + quit(_wa, ("Token parameter [name=" + variableName + "] equals to \"" + __testlib_part(result) + + "\", doesn't correspond to pattern \"" + p.src() + "\"").c_str()); + } +} + +void InStream::readWordTo(std::string &result, const std::string &ptrn, const std::string &variableName) { + return readWordTo(result, pattern(ptrn), variableName); +} + +void InStream::readTokenTo(std::string &result, const pattern &p, const std::string &variableName) { + return readWordTo(result, p, variableName); +} + +void InStream::readTokenTo(std::string &result, const std::string &ptrn, const std::string &variableName) { + return readWordTo(result, ptrn, variableName); +} + +#ifdef __GNUC__ +__attribute__((pure)) +#endif +static inline bool equals(long long integer, const char *s) { + if (integer == LLONG_MIN) + return strcmp(s, "-9223372036854775808") == 0; + + if (integer == 0LL) + return strcmp(s, "0") == 0; + + size_t length = strlen(s); + + if (length == 0) + return false; + + if (integer < 0 && s[0] != '-') + return false; + + if (integer < 0) + s++, length--, integer = -integer; + + if (length == 0) + return false; + + while (integer > 0) { + int digit = int(integer % 10); + + if (s[length - 1] != '0' + digit) + return false; + + length--; + integer /= 10; + } + + return length == 0; +} + +#ifdef __GNUC__ +__attribute__((pure)) +#endif +static inline bool equals(unsigned long long integer, const char *s) { + if (integer == ULLONG_MAX) + return strcmp(s, "18446744073709551615") == 0; + + if (integer == 0ULL) + return strcmp(s, "0") == 0; + + size_t length = strlen(s); + + if (length == 0) + return false; + + while (integer > 0) { + int digit = int(integer % 10); + + if (s[length - 1] != '0' + digit) + return false; + + length--; + integer /= 10; + } + + return length == 0; +} + +static inline double stringToDouble(InStream &in, const char *buffer) { + double retval; + + size_t length = strlen(buffer); + + int minusCount = 0; + int plusCount = 0; + int decimalPointCount = 0; + int digitCount = 0; + int eCount = 0; + + for (size_t i = 0; i < length; i++) { + if (('0' <= buffer[i] && buffer[i] <= '9') || buffer[i] == '.' + || buffer[i] == 'e' || buffer[i] == 'E' + || buffer[i] == '-' || buffer[i] == '+') { + if ('0' <= buffer[i] && buffer[i] <= '9') + digitCount++; + if (buffer[i] == 'e' || buffer[i] == 'E') + eCount++; + if (buffer[i] == '-') + minusCount++; + if (buffer[i] == '+') + plusCount++; + if (buffer[i] == '.') + decimalPointCount++; + } else + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + } + + // If for sure is not a number in standard notation or in e-notation. + if (digitCount == 0 || minusCount > 2 || plusCount > 2 || decimalPointCount > 1 || eCount > 1) + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + char *suffix = new char[length + 1]; + std::memset(suffix, 0, length + 1); + int scanned = std::sscanf(buffer, "%lf%s", &retval, suffix); + bool empty = strlen(suffix) == 0; + delete[] suffix; + + if (scanned == 1 || (scanned == 2 && empty)) { + if (__testlib_isNaN(retval)) + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + return retval; + } else + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); +} + +static inline double stringToDouble(InStream &in, const std::string& buffer) { + for (size_t i = 0; i < buffer.length(); i++) + if (buffer[i] == '\0') + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found (it contains \\0)").c_str()); + return stringToDouble(in, buffer.c_str()); +} + +static inline double stringToStrictDouble(InStream &in, const char *buffer, + int minAfterPointDigitCount, int maxAfterPointDigitCount) { + if (minAfterPointDigitCount < 0) + in.quit(_fail, "stringToStrictDouble: minAfterPointDigitCount should be non-negative."); + + if (minAfterPointDigitCount > maxAfterPointDigitCount) + in.quit(_fail, + "stringToStrictDouble: minAfterPointDigitCount should be less or equal to maxAfterPointDigitCount."); + + double retval; + + size_t length = strlen(buffer); + + if (length == 0 || length > 1000) + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + if (buffer[0] != '-' && (buffer[0] < '0' || buffer[0] > '9')) + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + int pointPos = -1; + for (size_t i = 1; i + 1 < length; i++) { + if (buffer[i] == '.') { + if (pointPos > -1) + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + pointPos = int(i); + } + if (buffer[i] != '.' && (buffer[i] < '0' || buffer[i] > '9')) + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + } + + if (buffer[length - 1] < '0' || buffer[length - 1] > '9') + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + int afterDigitsCount = (pointPos == -1 ? 0 : int(length) - pointPos - 1); + if (afterDigitsCount < minAfterPointDigitCount || afterDigitsCount > maxAfterPointDigitCount) + in.quit(_pe, ("Expected strict double with number of digits after point in range [" + + vtos(minAfterPointDigitCount) + + "," + + vtos(maxAfterPointDigitCount) + + "], but \"" + __testlib_part(buffer) + "\" found").c_str() + ); + + int firstDigitPos = -1; + for (size_t i = 0; i < length; i++) + if (buffer[i] >= '0' && buffer[i] <= '9') { + firstDigitPos = int(i); + break; + } + + if (firstDigitPos > 1 || firstDigitPos == -1) + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + if (buffer[firstDigitPos] == '0' && firstDigitPos + 1 < int(length) + && buffer[firstDigitPos + 1] >= '0' && buffer[firstDigitPos + 1] <= '9') + in.quit(_pe, ("Expected strict double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + char *suffix = new char[length + 1]; + std::memset(suffix, 0, length + 1); + int scanned = std::sscanf(buffer, "%lf%s", &retval, suffix); + bool empty = strlen(suffix) == 0; + delete[] suffix; + + if (scanned == 1 || (scanned == 2 && empty)) { + if (__testlib_isNaN(retval) || __testlib_isInfinite(retval)) + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); + if (buffer[0] == '-' && retval >= 0) + in.quit(_pe, ("Redundant minus in \"" + __testlib_part(buffer) + "\" found").c_str()); + return retval; + } else + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found").c_str()); +} + +static inline double stringToStrictDouble(InStream &in, const std::string& buffer, + int minAfterPointDigitCount, int maxAfterPointDigitCount) { + for (size_t i = 0; i < buffer.length(); i++) + if (buffer[i] == '\0') + in.quit(_pe, ("Expected double, but \"" + __testlib_part(buffer) + "\" found (it contains \\0)").c_str()); + return stringToStrictDouble(in, buffer.c_str(), minAfterPointDigitCount, maxAfterPointDigitCount); +} + +static inline long long stringToLongLong(InStream &in, const char *buffer) { + if (strcmp(buffer, "-9223372036854775808") == 0) + return LLONG_MIN; + + bool minus = false; + size_t length = strlen(buffer); + + if (length > 1 && buffer[0] == '-') + minus = true; + + if (length > 20) + in.quit(_pe, ("Expected integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + long long retval = 0LL; + + int zeroes = 0; + bool processingZeroes = true; + + for (int i = (minus ? 1 : 0); i < int(length); i++) { + if (buffer[i] == '0' && processingZeroes) + zeroes++; + else + processingZeroes = false; + + if (buffer[i] < '0' || buffer[i] > '9') + in.quit(_pe, ("Expected integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + retval = retval * 10 + (buffer[i] - '0'); + } + + if (retval < 0) + in.quit(_pe, ("Expected integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + if ((zeroes > 0 && (retval != 0 || minus)) || zeroes > 1) + in.quit(_pe, ("Expected integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + retval = (minus ? -retval : +retval); + + if (length < 19) + return retval; + + if (equals(retval, buffer)) + return retval; + else + in.quit(_pe, ("Expected int64, but \"" + __testlib_part(buffer) + "\" found").c_str()); +} + +static inline long long stringToLongLong(InStream &in, const std::string& buffer) { + for (size_t i = 0; i < buffer.length(); i++) + if (buffer[i] == '\0') + in.quit(_pe, ("Expected integer, but \"" + __testlib_part(buffer) + "\" found (it contains \\0)").c_str()); + return stringToLongLong(in, buffer.c_str()); +} + +static inline unsigned long long stringToUnsignedLongLong(InStream &in, const char *buffer) { + size_t length = strlen(buffer); + + if (length > 20) + in.quit(_pe, ("Expected unsigned integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + if (length > 1 && buffer[0] == '0') + in.quit(_pe, ("Expected unsigned integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + unsigned long long retval = 0LL; + for (int i = 0; i < int(length); i++) { + if (buffer[i] < '0' || buffer[i] > '9') + in.quit(_pe, ("Expected unsigned integer, but \"" + __testlib_part(buffer) + "\" found").c_str()); + retval = retval * 10 + (buffer[i] - '0'); + } + + if (length < 19) + return retval; + + if (length == 20 && strcmp(buffer, "18446744073709551615") > 0) + in.quit(_pe, ("Expected unsigned int64, but \"" + __testlib_part(buffer) + "\" found").c_str()); + + if (equals(retval, buffer)) + return retval; + else + in.quit(_pe, ("Expected unsigned int64, but \"" + __testlib_part(buffer) + "\" found").c_str()); +} + +static inline long long stringToUnsignedLongLong(InStream &in, const std::string& buffer) { + for (size_t i = 0; i < buffer.length(); i++) + if (buffer[i] == '\0') + in.quit(_pe, ("Expected unsigned integer, but \"" + __testlib_part(buffer) + "\" found (it contains \\0)").c_str()); + return stringToUnsignedLongLong(in, buffer.c_str()); +} + +int InStream::readInteger() { + if (!strict && seekEof()) + quit(_unexpected_eof, "Unexpected end of file - int32 expected"); + + readWordTo(_tmpReadToken); + + long long value = stringToLongLong(*this, _tmpReadToken); + if (value < INT_MIN || value > INT_MAX) + quit(_pe, ("Expected int32, but \"" + __testlib_part(_tmpReadToken) + "\" found").c_str()); + + return int(value); +} + +long long InStream::readLong() { + if (!strict && seekEof()) + quit(_unexpected_eof, "Unexpected end of file - int64 expected"); + + readWordTo(_tmpReadToken); + + return stringToLongLong(*this, _tmpReadToken); +} + +unsigned long long InStream::readUnsignedLong() { + if (!strict && seekEof()) + quit(_unexpected_eof, "Unexpected end of file - int64 expected"); + + readWordTo(_tmpReadToken); + + return stringToUnsignedLongLong(*this, _tmpReadToken); +} + +long long InStream::readLong(long long minv, long long maxv, const std::string &variableName) { + long long result = readLong(); + + if (result < minv || result > maxv) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, ("Integer " + vtos(result) + " violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + + "]").c_str()); + else + quit(_wa, ("Integer parameter [name=" + std::string(variableName) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + } else { + if (variableName.empty()) + quit(_wa, ("Integer element [index=" + vtos(readManyIteration) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + else + quit(_wa, + ("Integer element " + std::string(variableName) + "[" + vtos(readManyIteration) + "] equals to " + + vtos(result) + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + } + } + + if (strict && !variableName.empty()) + validator.addBoundsHit(variableName, ValidatorBoundsHit(minv == result, maxv == result)); + + return result; +} + +std::vector +InStream::readLongs(int size, long long minv, long long maxv, const std::string &variablesName, int indexBase) { + __testlib_readMany(readLongs, readLong(minv, maxv, variablesName), long long, true) +} + +std::vector InStream::readLongs(int size, int indexBase) { + __testlib_readMany(readLongs, readLong(), long long, true) +} + +unsigned long long +InStream::readUnsignedLong(unsigned long long minv, unsigned long long maxv, const std::string &variableName) { + unsigned long long result = readUnsignedLong(); + + if (result < minv || result > maxv) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, + ("Unsigned integer " + vtos(result) + " violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + + "]").c_str()); + else + quit(_wa, + ("Unsigned integer parameter [name=" + std::string(variableName) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + } else { + if (variableName.empty()) + quit(_wa, + ("Unsigned integer element [index=" + vtos(readManyIteration) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + else + quit(_wa, ("Unsigned integer element " + std::string(variableName) + "[" + vtos(readManyIteration) + + "] equals to " + vtos(result) + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + + "]").c_str()); + } + } + + if (strict && !variableName.empty()) + validator.addBoundsHit(variableName, ValidatorBoundsHit(minv == result, maxv == result)); + + return result; +} + +std::vector InStream::readUnsignedLongs(int size, unsigned long long minv, unsigned long long maxv, + const std::string &variablesName, int indexBase) { + __testlib_readMany(readUnsignedLongs, readUnsignedLong(minv, maxv, variablesName), unsigned long long, true) +} + +std::vector InStream::readUnsignedLongs(int size, int indexBase) { + __testlib_readMany(readUnsignedLongs, readUnsignedLong(), unsigned long long, true) +} + +unsigned long long +InStream::readLong(unsigned long long minv, unsigned long long maxv, const std::string &variableName) { + return readUnsignedLong(minv, maxv, variableName); +} + +int InStream::readInt() { + return readInteger(); +} + +int InStream::readInt(int minv, int maxv, const std::string &variableName) { + int result = readInt(); + + if (result < minv || result > maxv) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, ("Integer " + vtos(result) + " violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + + "]").c_str()); + else + quit(_wa, ("Integer parameter [name=" + std::string(variableName) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + } else { + if (variableName.empty()) + quit(_wa, ("Integer element [index=" + vtos(readManyIteration) + "] equals to " + vtos(result) + + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + else + quit(_wa, + ("Integer element " + std::string(variableName) + "[" + vtos(readManyIteration) + "] equals to " + + vtos(result) + ", violates the range [" + toHumanReadableString(minv) + ", " + toHumanReadableString(maxv) + "]").c_str()); + } + } + + if (strict && !variableName.empty()) + validator.addBoundsHit(variableName, ValidatorBoundsHit(minv == result, maxv == result)); + + return result; +} + +int InStream::readInteger(int minv, int maxv, const std::string &variableName) { + return readInt(minv, maxv, variableName); +} + +std::vector InStream::readInts(int size, int minv, int maxv, const std::string &variablesName, int indexBase) { + __testlib_readMany(readInts, readInt(minv, maxv, variablesName), int, true) +} + +std::vector InStream::readInts(int size, int indexBase) { + __testlib_readMany(readInts, readInt(), int, true) +} + +std::vector InStream::readIntegers(int size, int minv, int maxv, const std::string &variablesName, int indexBase) { + __testlib_readMany(readIntegers, readInt(minv, maxv, variablesName), int, true) +} + +std::vector InStream::readIntegers(int size, int indexBase) { + __testlib_readMany(readIntegers, readInt(), int, true) +} + +double InStream::readReal() { + if (!strict && seekEof()) + quit(_unexpected_eof, "Unexpected end of file - double expected"); + + return stringToDouble(*this, readWord()); +} + +double InStream::readDouble() { + return readReal(); +} + +double InStream::readReal(double minv, double maxv, const std::string &variableName) { + double result = readReal(); + + if (result < minv || result > maxv) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, ("Double " + vtos(result) + " violates the range [" + vtos(minv) + ", " + vtos(maxv) + + "]").c_str()); + else + quit(_wa, ("Double parameter [name=" + std::string(variableName) + "] equals to " + vtos(result) + + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str()); + } else { + if (variableName.empty()) + quit(_wa, ("Double element [index=" + vtos(readManyIteration) + "] equals to " + vtos(result) + + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str()); + else + quit(_wa, + ("Double element " + std::string(variableName) + "[" + vtos(readManyIteration) + "] equals to " + + vtos(result) + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str()); + } + } + + if (strict && !variableName.empty()) + validator.addBoundsHit(variableName, ValidatorBoundsHit( + doubleDelta(minv, result) < ValidatorBoundsHit::EPS, + doubleDelta(maxv, result) < ValidatorBoundsHit::EPS + )); + + return result; +} + +std::vector +InStream::readReals(int size, double minv, double maxv, const std::string &variablesName, int indexBase) { + __testlib_readMany(readReals, readReal(minv, maxv, variablesName), double, true) +} + +std::vector InStream::readReals(int size, int indexBase) { + __testlib_readMany(readReals, readReal(), double, true) +} + +double InStream::readDouble(double minv, double maxv, const std::string &variableName) { + return readReal(minv, maxv, variableName); +} + +std::vector +InStream::readDoubles(int size, double minv, double maxv, const std::string &variablesName, int indexBase) { + __testlib_readMany(readDoubles, readDouble(minv, maxv, variablesName), double, true) +} + +std::vector InStream::readDoubles(int size, int indexBase) { + __testlib_readMany(readDoubles, readDouble(), double, true) +} + +double InStream::readStrictReal(double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variableName) { + if (!strict && seekEof()) + quit(_unexpected_eof, "Unexpected end of file - strict double expected"); + + double result = stringToStrictDouble(*this, readWord(), minAfterPointDigitCount, maxAfterPointDigitCount); + + if (result < minv || result > maxv) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, ("Strict double " + vtos(result) + " violates the range [" + vtos(minv) + ", " + vtos(maxv) + + "]").c_str()); + else + quit(_wa, + ("Strict double parameter [name=" + std::string(variableName) + "] equals to " + vtos(result) + + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str()); + } else { + if (variableName.empty()) + quit(_wa, ("Strict double element [index=" + vtos(readManyIteration) + "] equals to " + vtos(result) + + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + "]").c_str()); + else + quit(_wa, ("Strict double element " + std::string(variableName) + "[" + vtos(readManyIteration) + + "] equals to " + vtos(result) + ", violates the range [" + vtos(minv) + ", " + vtos(maxv) + + "]").c_str()); + } + } + + if (strict && !variableName.empty()) + validator.addBoundsHit(variableName, ValidatorBoundsHit( + doubleDelta(minv, result) < ValidatorBoundsHit::EPS, + doubleDelta(maxv, result) < ValidatorBoundsHit::EPS + )); + + return result; +} + +std::vector InStream::readStrictReals(int size, double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variablesName, int indexBase) { + __testlib_readMany(readStrictReals, + readStrictReal(minv, maxv, minAfterPointDigitCount, maxAfterPointDigitCount, variablesName), + double, true) +} + +double InStream::readStrictDouble(double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variableName) { + return readStrictReal(minv, maxv, + minAfterPointDigitCount, maxAfterPointDigitCount, + variableName); +} + +std::vector InStream::readStrictDoubles(int size, double minv, double maxv, + int minAfterPointDigitCount, int maxAfterPointDigitCount, + const std::string &variablesName, int indexBase) { + __testlib_readMany(readStrictDoubles, + readStrictDouble(minv, maxv, minAfterPointDigitCount, maxAfterPointDigitCount, variablesName), + double, true) +} + +bool InStream::eof() { + if (!strict && NULL == reader) + return true; + + return reader->eof(); +} + +bool InStream::seekEof() { + if (!strict && NULL == reader) + return true; + skipBlanks(); + return eof(); +} + +bool InStream::eoln() { + if (!strict && NULL == reader) + return true; + + int c = reader->nextChar(); + + if (!strict) { + if (c == EOFC) + return true; + + if (c == CR) { + c = reader->nextChar(); + + if (c != LF) { + reader->unreadChar(c); + reader->unreadChar(CR); + return false; + } else + return true; + } + + if (c == LF) + return true; + + reader->unreadChar(c); + return false; + } else { + bool returnCr = false; + +#if (defined(ON_WINDOWS) && !defined(FOR_LINUX)) || defined(FOR_WINDOWS) + if (c != CR) { + reader->unreadChar(c); + return false; + } else { + if (!returnCr) + returnCr = true; + c = reader->nextChar(); + } +#endif + if (c != LF) { + reader->unreadChar(c); + if (returnCr) + reader->unreadChar(CR); + return false; + } + + return true; + } +} + +void InStream::readEoln() { + lastLine = reader->getLine(); + if (!eoln()) + quit(_pe, "Expected EOLN"); +} + +void InStream::readEof() { + lastLine = reader->getLine(); + if (!eof()) + quit(_pe, "Expected EOF"); + + if (TestlibFinalizeGuard::alive && this == &inf) + testlibFinalizeGuard.readEofCount++; +} + +bool InStream::seekEoln() { + if (!strict && NULL == reader) + return true; + + int cur; + do { + cur = reader->nextChar(); + } while (cur == SPACE || cur == TAB); + + reader->unreadChar(cur); + return eoln(); +} + +void InStream::nextLine() { + readLine(); +} + +void InStream::readStringTo(std::string &result) { + if (NULL == reader) + quit(_pe, "Expected line"); + + result.clear(); + + for (;;) { + int cur = reader->curChar(); + + if (cur == LF || cur == EOFC) + break; + + if (cur == CR) { + cur = reader->nextChar(); + if (reader->curChar() == LF) { + reader->unreadChar(cur); + break; + } + } + + lastLine = reader->getLine(); + result += char(reader->nextChar()); + } + + if (strict) + readEoln(); + else + eoln(); +} + +std::string InStream::readString() { + readStringTo(_tmpReadToken); + return _tmpReadToken; +} + +std::vector InStream::readStrings(int size, int indexBase) { + __testlib_readMany(readStrings, readString(), std::string, false) +} + +void InStream::readStringTo(std::string &result, const pattern &p, const std::string &variableName) { + readStringTo(result); + if (!p.matches(result)) { + if (readManyIteration == NO_INDEX) { + if (variableName.empty()) + quit(_wa, ("Line \"" + __testlib_part(result) + "\" doesn't correspond to pattern \"" + p.src() + + "\"").c_str()); + else + quit(_wa, ("Line [name=" + variableName + "] equals to \"" + __testlib_part(result) + + "\", doesn't correspond to pattern \"" + p.src() + "\"").c_str()); + } else { + if (variableName.empty()) + quit(_wa, + ("Line element [index=" + vtos(readManyIteration) + "] equals to \"" + __testlib_part(result) + + "\" doesn't correspond to pattern \"" + p.src() + "\"").c_str()); + else + quit(_wa, + ("Line element " + std::string(variableName) + "[" + vtos(readManyIteration) + "] equals to \"" + + __testlib_part(result) + "\", doesn't correspond to pattern \"" + p.src() + "\"").c_str()); + } + } +} + +void InStream::readStringTo(std::string &result, const std::string &ptrn, const std::string &variableName) { + readStringTo(result, pattern(ptrn), variableName); +} + +std::string InStream::readString(const pattern &p, const std::string &variableName) { + readStringTo(_tmpReadToken, p, variableName); + return _tmpReadToken; +} + +std::vector +InStream::readStrings(int size, const pattern &p, const std::string &variablesName, int indexBase) { + __testlib_readMany(readStrings, readString(p, variablesName), std::string, false) +} + +std::string InStream::readString(const std::string &ptrn, const std::string &variableName) { + readStringTo(_tmpReadToken, ptrn, variableName); + return _tmpReadToken; +} + +std::vector +InStream::readStrings(int size, const std::string &ptrn, const std::string &variablesName, int indexBase) { + pattern p(ptrn); + __testlib_readMany(readStrings, readString(p, variablesName), std::string, false) +} + +void InStream::readLineTo(std::string &result) { + readStringTo(result); +} + +std::string InStream::readLine() { + return readString(); +} + +std::vector InStream::readLines(int size, int indexBase) { + __testlib_readMany(readLines, readString(), std::string, false) +} + +void InStream::readLineTo(std::string &result, const pattern &p, const std::string &variableName) { + readStringTo(result, p, variableName); +} + +void InStream::readLineTo(std::string &result, const std::string &ptrn, const std::string &variableName) { + readStringTo(result, ptrn, variableName); +} + +std::string InStream::readLine(const pattern &p, const std::string &variableName) { + return readString(p, variableName); +} + +std::vector +InStream::readLines(int size, const pattern &p, const std::string &variablesName, int indexBase) { + __testlib_readMany(readLines, readString(p, variablesName), std::string, false) +} + +std::string InStream::readLine(const std::string &ptrn, const std::string &variableName) { + return readString(ptrn, variableName); +} + +std::vector +InStream::readLines(int size, const std::string &ptrn, const std::string &variablesName, int indexBase) { + pattern p(ptrn); + __testlib_readMany(readLines, readString(p, variablesName), std::string, false) +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 4))) +#endif +void InStream::ensuref(bool cond, const char *format, ...) { + if (!cond) { + FMT_TO_RESULT(format, format, message); + this->__testlib_ensure(cond, message); + } +} + +void InStream::__testlib_ensure(bool cond, std::string message) { + if (!cond) + this->quit(_wa, message.c_str()); +} + +void InStream::close() { + if (NULL != reader) { + reader->close(); + delete reader; + reader = NULL; + } + + opened = false; +} + +NORETURN void quit(TResult result, const std::string &msg) { + ouf.quit(result, msg.c_str()); +} + +NORETURN void quit(TResult result, const char *msg) { + ouf.quit(result, msg); +} + +NORETURN void __testlib_quitp(double points, const char *message) { + __testlib_points = points; + std::string stringPoints = removeDoubleTrailingZeroes(format("%.10f", points)); + + std::string quitMessage; + if (NULL == message || 0 == strlen(message)) + quitMessage = stringPoints; + else + quitMessage = stringPoints + " " + message; + + quit(_points, quitMessage.c_str()); +} + +NORETURN void __testlib_quitp(int points, const char *message) { + __testlib_points = points; + std::string stringPoints = format("%d", points); + + std::string quitMessage; + if (NULL == message || 0 == strlen(message)) + quitMessage = stringPoints; + else + quitMessage = stringPoints + " " + message; + + quit(_points, quitMessage.c_str()); +} + +NORETURN void quitp(float points, const std::string &message = "") { + __testlib_quitp(double(points), message.c_str()); +} + +NORETURN void quitp(double points, const std::string &message = "") { + __testlib_quitp(points, message.c_str()); +} + +NORETURN void quitp(long double points, const std::string &message = "") { + __testlib_quitp(double(points), message.c_str()); +} + +NORETURN void quitp(int points, const std::string &message = "") { + __testlib_quitp(points, message.c_str()); +} + +NORETURN void quitpi(const std::string &points_info, const std::string &message = "") { + if (points_info.find(' ') != std::string::npos) + quit(_fail, "Parameter 'points_info' can't contain spaces"); + if (message.empty()) + quit(_points, ("points_info=" + points_info).c_str()); + else + quit(_points, ("points_info=" + points_info + " " + message).c_str()); +} + +template +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))) +#endif +NORETURN void quitp(F points, const char *format, ...) { + FMT_TO_RESULT(format, format, message); + quitp(points, message); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))) +#endif +NORETURN void quitf(TResult result, const char *format, ...) { + FMT_TO_RESULT(format, format, message); + quit(result, message); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 4))) +#endif +void quitif(bool condition, TResult result, const char *format, ...) { + if (condition) { + FMT_TO_RESULT(format, format, message); + quit(result, message); + } +} + +NORETURN void __testlib_help() { + InStream::textColor(InStream::LightCyan); + std::fprintf(stderr, "TESTLIB %s, https://github.com/MikeMirzayanov/testlib/ ", VERSION); + std::fprintf(stderr, "by Mike Mirzayanov, copyright(c) 2005-2020\n"); + std::fprintf(stderr, "Checker name: \"%s\"\n", checkerName.c_str()); + InStream::textColor(InStream::LightGray); + + std::fprintf(stderr, "\n"); + std::fprintf(stderr, "Latest features: \n"); + for (size_t i = 0; i < sizeof(latestFeatures) / sizeof(char *); i++) { + std::fprintf(stderr, "*) %s\n", latestFeatures[i]); + } + std::fprintf(stderr, "\n"); + + std::fprintf(stderr, "Program must be run with the following arguments: \n"); + std::fprintf(stderr, " [--testset testset] [--group group] [ [<-appes>]]\n\n"); + + __testlib_exitCode = FAIL_EXIT_CODE; + std::exit(FAIL_EXIT_CODE); +} + +static void __testlib_ensuresPreconditions() { + // testlib assumes: sizeof(int) = 4. + __TESTLIB_STATIC_ASSERT(sizeof(int) == 4); + + // testlib assumes: INT_MAX == 2147483647. + __TESTLIB_STATIC_ASSERT(INT_MAX == 2147483647); + + // testlib assumes: sizeof(long long) = 8. + __TESTLIB_STATIC_ASSERT(sizeof(long long) == 8); + + // testlib assumes: sizeof(double) = 8. + __TESTLIB_STATIC_ASSERT(sizeof(double) == 8); + + // testlib assumes: no -ffast-math. + if (!__testlib_isNaN(+__testlib_nan())) + quit(_fail, "Function __testlib_isNaN is not working correctly: possible reason is '-ffast-math'"); + if (!__testlib_isNaN(-__testlib_nan())) + quit(_fail, "Function __testlib_isNaN is not working correctly: possible reason is '-ffast-math'"); +} + +std::string __testlib_testset; + +std::string getTestset() { + return __testlib_testset; +} + +std::string __testlib_group; + +std::string getGroup() { + return __testlib_group; +} + +static void __testlib_set_testset_and_group(int argc, char* argv[]) { + for (int i = 1; i < argc; i++) { + if (!strcmp("--testset", argv[i])) { + if (i + 1 < argc && strlen(argv[i + 1]) > 0) + __testlib_testset = argv[++i]; + else + quit(_fail, std::string("Expected non-empty testset after --testset command line parameter")); + } else if (!strcmp("--group", argv[i])) { + if (i + 1 < argc) + __testlib_group = argv[++i]; + else + quit(_fail, std::string("Expected group after --group command line parameter")); + } + } +} + +void registerGen(int argc, char *argv[], int randomGeneratorVersion) { + if (randomGeneratorVersion < 0 || randomGeneratorVersion > 1) + quitf(_fail, "Random generator version is expected to be 0 or 1."); + random_t::version = randomGeneratorVersion; + + __testlib_ensuresPreconditions(); + TestlibFinalizeGuard::registered = true; + + testlibMode = _generator; + __testlib_set_binary(stdin); + rnd.setSeed(argc, argv); + +#if __cplusplus > 199711L || defined(_MSC_VER) + prepareOpts(argc, argv); +#endif +} + +#ifdef USE_RND_AS_BEFORE_087 +void registerGen(int argc, char* argv[]) +{ + registerGen(argc, argv, 0); +} +#else +#ifdef __GNUC__ +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 4)) +__attribute__ ((deprecated("Use registerGen(argc, argv, 0) or registerGen(argc, argv, 1)." +" The third parameter stands for the random generator version." +" If you are trying to compile old generator use macro -DUSE_RND_AS_BEFORE_087 or registerGen(argc, argv, 0)." +" Version 1 has been released on Spring, 2013. Use it to write new generators."))) +#else +__attribute__ ((deprecated)) +#endif +#endif +#ifdef _MSC_VER +__declspec(deprecated("Use registerGen(argc, argv, 0) or registerGen(argc, argv, 1)." + " The third parameter stands for the random generator version." + " If you are trying to compile old generator use macro -DUSE_RND_AS_BEFORE_087 or registerGen(argc, argv, 0)." + " Version 1 has been released on Spring, 2013. Use it to write new generators.")) +#endif +void registerGen(int argc, char *argv[]) { + std::fprintf(stderr, "Use registerGen(argc, argv, 0) or registerGen(argc, argv, 1)." + " The third parameter stands for the random generator version." + " If you are trying to compile old generator use macro -DUSE_RND_AS_BEFORE_087 or registerGen(argc, argv, 0)." + " Version 1 has been released on Spring, 2013. Use it to write new generators.\n\n"); + registerGen(argc, argv, 0); +} +#endif + +void registerInteraction(int argc, char *argv[]) { + __testlib_ensuresPreconditions(); + __testlib_set_testset_and_group(argc, argv); + TestlibFinalizeGuard::registered = true; + + testlibMode = _interactor; + __testlib_set_binary(stdin); + + if (argc > 1 && !strcmp("--help", argv[1])) + __testlib_help(); + + if (argc < 3 || argc > 6) { + quit(_fail, std::string("Program must be run with the following arguments: ") + + std::string(" [ [ [<-appes>]]]") + + "\nUse \"--help\" to get help information"); + } + + if (argc <= 4) { + resultName = ""; + appesMode = false; + } + +#ifndef EJUDGE + if (argc == 5) { + resultName = argv[4]; + appesMode = false; + } + + if (argc == 6) { + if (strcmp("-APPES", argv[5]) && strcmp("-appes", argv[5])) { + quit(_fail, std::string("Program must be run with the following arguments: ") + + " [ [<-appes>]]"); + } else { + resultName = argv[4]; + appesMode = true; + } + } +#endif + + inf.init(argv[1], _input); + + tout.open(argv[2], std::ios_base::out); + if (tout.fail() || !tout.is_open()) + quit(_fail, std::string("Can not write to the test-output-file '") + argv[2] + std::string("'")); + + ouf.init(stdin, _output); + + if (argc >= 4) + ans.init(argv[3], _answer); + else + ans.name = "unopened answer stream"; +} + +void registerValidation() { + __testlib_ensuresPreconditions(); + TestlibFinalizeGuard::registered = true; + + testlibMode = _validator; + + __testlib_set_binary(stdin); + __testlib_set_binary(stdout); + __testlib_set_binary(stderr); + + inf.init(stdin, _input); + inf.strict = true; +} + +void registerValidation(int argc, char *argv[]) { + registerValidation(); + __testlib_set_testset_and_group(argc, argv); + + validator.initialize(); + TestlibFinalizeGuard::registered = true; + + std::string comment = "Validator must be run with the following arguments:" + " [--testset testset]" + " [--group group]" + " [--testOverviewLogFileName fileName]" + " [--testMarkupFileName fileName]" + " [--testCase testCase]" + " [--testCaseFileName fileName]" + ; + + for (int i = 1; i < argc; i++) { + if (!strcmp("--testset", argv[i])) { + if (i + 1 < argc && strlen(argv[i + 1]) > 0) + validator.setTestset(argv[++i]); + else + quit(_fail, comment); + } + if (!strcmp("--group", argv[i])) { + if (i + 1 < argc) + validator.setGroup(argv[++i]); + else + quit(_fail, comment); + } + if (!strcmp("--testOverviewLogFileName", argv[i])) { + if (i + 1 < argc) + validator.setTestOverviewLogFileName(argv[++i]); + else + quit(_fail, comment); + } + if (!strcmp("--testMarkupFileName", argv[i])) { + if (i + 1 < argc) + validator.setTestMarkupFileName(argv[++i]); + else + quit(_fail, comment); + } + if (!strcmp("--testCase", argv[i])) { + if (i + 1 < argc) { + long long testCase = stringToLongLong(inf, argv[++i]); + if (testCase < 1 || testCase >= __TESTLIB_MAX_TEST_CASE) + quit(_fail, format("Argument testCase should be between 1 and %d, but ", __TESTLIB_MAX_TEST_CASE) + + toString(testCase) + " found"); + validator.setTestCase(int(testCase)); + } else + quit(_fail, comment); + } + if (!strcmp("--testCaseFileName", argv[i])) { + if (i + 1 < argc) { + validator.setTestCaseFileName(argv[++i]); + } else + quit(_fail, comment); + } + } +} + +void addFeature(const std::string &feature) { + if (testlibMode != _validator) + quit(_fail, "Features are supported in validators only."); + validator.addFeature(feature); +} + +void feature(const std::string &feature) { + if (testlibMode != _validator) + quit(_fail, "Features are supported in validators only."); + validator.feature(feature); +} + +class Checker { +private: + bool _initialized; + std::string _testset; + std::string _group; + +public: + Checker() : _initialized(false), _testset("tests"), _group() { + } + + void initialize() { + _initialized = true; + } + + std::string testset() const { + if (!_initialized) + __testlib_fail("Checker should be initialized with registerTestlibCmd(argc, argv) instead of registerTestlibCmd() to support checker.testset()"); + return _testset; + } + + std::string group() const { + if (!_initialized) + __testlib_fail("Checker should be initialized with registerTestlibCmd(argc, argv) instead of registerTestlibCmd() to support checker.group()"); + return _group; + } + + void setTestset(const char *const testset) { + _testset = testset; + } + + void setGroup(const char *const group) { + _group = group; + } +} checker; + +void registerTestlibCmd(int argc, char *argv[]) { + __testlib_ensuresPreconditions(); + __testlib_set_testset_and_group(argc, argv); + TestlibFinalizeGuard::registered = true; + + testlibMode = _checker; + __testlib_set_binary(stdin); + + std::vector args(1, argv[0]); + checker.initialize(); + + for (int i = 1; i < argc; i++) { + if (!strcmp("--testset", argv[i])) { + if (i + 1 < argc && strlen(argv[i + 1]) > 0) + checker.setTestset(argv[++i]); + else + quit(_fail, std::string("Expected testset after --testset command line parameter")); + } else if (!strcmp("--group", argv[i])) { + if (i + 1 < argc) + checker.setGroup(argv[++i]); + else + quit(_fail, std::string("Expected group after --group command line parameter")); + } else + args.push_back(argv[i]); + } + + argc = int(args.size()); + if (argc > 1 && "--help" == args[1]) + __testlib_help(); + + if (argc < 4 || argc > 6) { + quit(_fail, std::string("Program must be run with the following arguments: ") + + std::string("[--testset testset] [--group group] [ [<-appes>]]") + + "\nUse \"--help\" to get help information"); + } + + if (argc == 4) { + resultName = ""; + appesMode = false; + } + + if (argc == 5) { + resultName = args[4]; + appesMode = false; + } + + if (argc == 6) { + if ("-APPES" != args[5] && "-appes" != args[5]) { + quit(_fail, std::string("Program must be run with the following arguments: ") + + " [ [<-appes>]]"); + } else { + resultName = args[4]; + appesMode = true; + } + } + + #ifdef BOCA_SUPPORT + inf.init(argv[3], _input); + ouf.init(argv[1], _output); + ans.init(argv[2], _answer); + #else + inf.init(argv[1], _input); + ouf.init(argv[2], _output); + ans.init(argv[3], _answer); + #endif +} + +void registerTestlib(int argc, ...) { + if (argc < 3 || argc > 5) + quit(_fail, std::string("Program must be run with the following arguments: ") + + " [ [<-appes>]]"); + + char **argv = new char *[argc + 1]; + + va_list ap; + va_start(ap, argc); + argv[0] = NULL; + for (int i = 0; i < argc; i++) { + argv[i + 1] = va_arg(ap, char*); + } + va_end(ap); + + registerTestlibCmd(argc + 1, argv); + delete[] argv; +} + +static inline void __testlib_ensure(bool cond, const std::string &msg) { + if (!cond) + quit(_fail, msg.c_str()); +} + +#ifdef __GNUC__ +__attribute__((unused)) +#endif +static inline void __testlib_ensure(bool cond, const char *msg) { + if (!cond) + quit(_fail, msg); +} + +#define ensure(cond) __testlib_ensure(cond, "Condition failed: \"" #cond "\"") +#define STRINGIZE_DETAIL(x) #x +#define STRINGIZE(x) STRINGIZE_DETAIL(x) +#define ensure_ext(cond) __testlib_ensure(cond, "Line " STRINGIZE(__LINE__) ": Condition failed: \"" #cond "\"") + +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))) +#endif +inline void ensuref(bool cond, const char *format, ...) { + if (!cond) { + FMT_TO_RESULT(format, format, message); + __testlib_ensure(cond, message); + } +} + +NORETURN static void __testlib_fail(const std::string &message) { + quitf(_fail, "%s", message.c_str()); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +void setName(const char *format, ...) { + FMT_TO_RESULT(format, format, name); + checkerName = name; +} + +/* + * Do not use random_shuffle, because it will produce different result + * for different C++ compilers. + * + * This implementation uses testlib random_t to produce random numbers, so + * it is stable. + */ +template +void shuffle(_RandomAccessIter __first, _RandomAccessIter __last) { + if (__first == __last) return; + for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i) + std::iter_swap(__i, __first + rnd.next(int(__i - __first) + 1)); +} + + +template +#if defined(__GNUC__) && !defined(__clang__) +__attribute__ ((error("Don't use random_shuffle(), use shuffle() instead"))) +#endif +void random_shuffle(_RandomAccessIter, _RandomAccessIter) { + quitf(_fail, "Don't use random_shuffle(), use shuffle() instead"); +} + +#ifdef __GLIBC__ +# define RAND_THROW_STATEMENT throw() +#else +# define RAND_THROW_STATEMENT +#endif + +#if defined(__GNUC__) && !defined(__clang__) + +__attribute__ ((error("Don't use rand(), use rnd.next() instead"))) +#endif +#ifdef _MSC_VER +# pragma warning( disable : 4273 ) +#endif +int rand() RAND_THROW_STATEMENT +{ + quitf(_fail, "Don't use rand(), use rnd.next() instead"); + + /* This line never runs. */ + //throw "Don't use rand(), use rnd.next() instead"; +} + +#if defined(__GNUC__) && !defined(__clang__) + +__attribute__ ((error("Don't use srand(), you should use " +"'registerGen(argc, argv, 1);' to initialize generator seed " +"by hash code of the command line params. The third parameter " +"is randomGeneratorVersion (currently the latest is 1)."))) +#endif +#ifdef _MSC_VER +# pragma warning( disable : 4273 ) +#endif +void srand(unsigned int seed) RAND_THROW_STATEMENT +{ + quitf(_fail, "Don't use srand(), you should use " + "'registerGen(argc, argv, 1);' to initialize generator seed " + "by hash code of the command line params. The third parameter " + "is randomGeneratorVersion (currently the latest is 1) [ignored seed=%u].", seed); +} + +void startTest(int test) { + const std::string testFileName = vtos(test); + if (NULL == freopen(testFileName.c_str(), "wt", stdout)) + __testlib_fail("Unable to write file '" + testFileName + "'"); +} + +inline std::string upperCase(std::string s) { + for (size_t i = 0; i < s.length(); i++) + if ('a' <= s[i] && s[i] <= 'z') + s[i] = char(s[i] - 'a' + 'A'); + return s; +} + +inline std::string lowerCase(std::string s) { + for (size_t i = 0; i < s.length(); i++) + if ('A' <= s[i] && s[i] <= 'Z') + s[i] = char(s[i] - 'A' + 'a'); + return s; +} + +inline std::string compress(const std::string &s) { + return __testlib_part(s); +} + +inline std::string englishEnding(int x) { + x %= 100; + if (x / 10 == 1) + return "th"; + if (x % 10 == 1) + return "st"; + if (x % 10 == 2) + return "nd"; + if (x % 10 == 3) + return "rd"; + return "th"; +} + +template +std::string join(_ForwardIterator first, _ForwardIterator last, _Separator separator) { + std::stringstream ss; + bool repeated = false; + for (_ForwardIterator i = first; i != last; i++) { + if (repeated) + ss << separator; + else + repeated = true; + ss << *i; + } + return ss.str(); +} + +template +std::string join(_ForwardIterator first, _ForwardIterator last) { + return join(first, last, ' '); +} + +template +std::string join(const _Collection &collection, _Separator separator) { + return join(collection.begin(), collection.end(), separator); +} + +template +std::string join(const _Collection &collection) { + return join(collection, ' '); +} + +/** + * Splits string s by character separator returning exactly k+1 items, + * where k is the number of separator occurences. + */ +std::vector split(const std::string &s, char separator) { + std::vector result; + std::string item; + for (size_t i = 0; i < s.length(); i++) + if (s[i] == separator) { + result.push_back(item); + item = ""; + } else + item += s[i]; + result.push_back(item); + return result; +} + +/** + * Splits string s by character separators returning exactly k+1 items, + * where k is the number of separator occurences. + */ +std::vector split(const std::string &s, const std::string &separators) { + if (separators.empty()) + return std::vector(1, s); + + std::vector isSeparator(256); + for (size_t i = 0; i < separators.size(); i++) + isSeparator[(unsigned char) (separators[i])] = true; + + std::vector result; + std::string item; + for (size_t i = 0; i < s.length(); i++) + if (isSeparator[(unsigned char) (s[i])]) { + result.push_back(item); + item = ""; + } else + item += s[i]; + result.push_back(item); + return result; +} + +/** + * Splits string s by character separator returning non-empty items. + */ +std::vector tokenize(const std::string &s, char separator) { + std::vector result; + std::string item; + for (size_t i = 0; i < s.length(); i++) + if (s[i] == separator) { + if (!item.empty()) + result.push_back(item); + item = ""; + } else + item += s[i]; + if (!item.empty()) + result.push_back(item); + return result; +} + +/** + * Splits string s by character separators returning non-empty items. + */ +std::vector tokenize(const std::string &s, const std::string &separators) { + if (separators.empty()) + return std::vector(1, s); + + std::vector isSeparator(256); + for (size_t i = 0; i < separators.size(); i++) + isSeparator[(unsigned char) (separators[i])] = true; + + std::vector result; + std::string item; + for (size_t i = 0; i < s.length(); i++) + if (isSeparator[(unsigned char) (s[i])]) { + if (!item.empty()) + result.push_back(item); + item = ""; + } else + item += s[i]; + + if (!item.empty()) + result.push_back(item); + + return result; +} + +NORETURN void __testlib_expectedButFound(TResult result, std::string expected, std::string found, const char *prepend) { + std::string message; + if (strlen(prepend) != 0) + message = format("%s: expected '%s', but found '%s'", + compress(prepend).c_str(), compress(expected).c_str(), compress(found).c_str()); + else + message = format("expected '%s', but found '%s'", + compress(expected).c_str(), compress(found).c_str()); + quit(result, message); +} + +NORETURN void __testlib_expectedButFound(TResult result, double expected, double found, const char *prepend) { + std::string expectedString = removeDoubleTrailingZeroes(format("%.12f", expected)); + std::string foundString = removeDoubleTrailingZeroes(format("%.12f", found)); + __testlib_expectedButFound(result, expectedString, foundString, prepend); +} + +template +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void expectedButFound(TResult result, T expected, T found, const char *prependFormat = "", ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + std::string expectedString = vtos(expected); + std::string foundString = vtos(found); + __testlib_expectedButFound(result, expectedString, foundString, prepend.c_str()); +} + +template<> +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void +expectedButFound(TResult result, std::string expected, std::string found, const char *prependFormat, ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + __testlib_expectedButFound(result, expected, found, prepend.c_str()); +} + +template<> +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void expectedButFound(TResult result, double expected, double found, const char *prependFormat, ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + std::string expectedString = removeDoubleTrailingZeroes(format("%.12f", expected)); + std::string foundString = removeDoubleTrailingZeroes(format("%.12f", found)); + __testlib_expectedButFound(result, expectedString, foundString, prepend.c_str()); +} + +template<> +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void +expectedButFound(TResult result, const char *expected, const char *found, const char *prependFormat, + ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + __testlib_expectedButFound(result, std::string(expected), std::string(found), prepend.c_str()); +} + +template<> +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void expectedButFound(TResult result, float expected, float found, const char *prependFormat, ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + __testlib_expectedButFound(result, double(expected), double(found), prepend.c_str()); +} + +template<> +#ifdef __GNUC__ +__attribute__ ((format (printf, 4, 5))) +#endif +NORETURN void +expectedButFound(TResult result, long double expected, long double found, const char *prependFormat, ...) { + FMT_TO_RESULT(prependFormat, prependFormat, prepend); + __testlib_expectedButFound(result, double(expected), double(found), prepend.c_str()); +} + +#if __cplusplus > 199711L || defined(_MSC_VER) +template +struct is_iterable { + template + static char test(typename U::iterator *x); + + template + static long test(U *x); + + static const bool value = sizeof(test(0)) == 1; +}; + +template +struct __testlib_enable_if { +}; + +template +struct __testlib_enable_if { + typedef T type; +}; + +template +typename __testlib_enable_if::value, void>::type __testlib_print_one(const T &t) { + std::cout << t; +} + +template +typename __testlib_enable_if::value, void>::type __testlib_print_one(const T &t) { + bool first = true; + for (typename T::const_iterator i = t.begin(); i != t.end(); i++) { + if (first) + first = false; + else + std::cout << " "; + std::cout << *i; + } +} + +template<> +typename __testlib_enable_if::value, void>::type +__testlib_print_one(const std::string &t) { + std::cout << t; +} + +template +void __println_range(A begin, B end) { + bool first = true; + for (B i = B(begin); i != end; i++) { + if (first) + first = false; + else + std::cout << " "; + __testlib_print_one(*i); + } + std::cout << std::endl; +} + +template +struct is_iterator { + static T makeT(); + + typedef void *twoptrs[2]; + + static twoptrs &test(...); + + template + static typename R::iterator_category *test(R); + + template + static void *test(R *); + + static const bool value = sizeof(test(makeT())) == sizeof(void *); +}; + +template +struct is_iterator::value>::type> { + static const bool value = false; +}; + +template +typename __testlib_enable_if::value, void>::type println(const A &a, const B &b) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << std::endl; +} + +template +typename __testlib_enable_if::value, void>::type println(const A &a, const B &b) { + __println_range(a, b); +} + +template +void println(const A *a, const A *b) { + __println_range(a, b); +} + +template<> +void println(const char *a, const char *b) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << std::endl; +} + +template +void println(const T &x) { + __testlib_print_one(x); + std::cout << std::endl; +} + +template +void println(const A &a, const B &b, const C &c) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << " "; + __testlib_print_one(c); + std::cout << std::endl; +} + +template +void println(const A &a, const B &b, const C &c, const D &d) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << " "; + __testlib_print_one(c); + std::cout << " "; + __testlib_print_one(d); + std::cout << std::endl; +} + +template +void println(const A &a, const B &b, const C &c, const D &d, const E &e) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << " "; + __testlib_print_one(c); + std::cout << " "; + __testlib_print_one(d); + std::cout << " "; + __testlib_print_one(e); + std::cout << std::endl; +} + +template +void println(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << " "; + __testlib_print_one(c); + std::cout << " "; + __testlib_print_one(d); + std::cout << " "; + __testlib_print_one(e); + std::cout << " "; + __testlib_print_one(f); + std::cout << std::endl; +} + +template +void println(const A &a, const B &b, const C &c, const D &d, const E &e, const F &f, const G &g) { + __testlib_print_one(a); + std::cout << " "; + __testlib_print_one(b); + std::cout << " "; + __testlib_print_one(c); + std::cout << " "; + __testlib_print_one(d); + std::cout << " "; + __testlib_print_one(e); + std::cout << " "; + __testlib_print_one(f); + std::cout << " "; + __testlib_print_one(g); + std::cout << std::endl; +} + +/* opts */ + +/** + * A struct for a singular testlib opt, containing the raw string value, + * and a boolean value for marking whether the opt is used. + */ +struct TestlibOpt { + std::string value; + bool used; + + TestlibOpt() : value(), used(false) {} +}; + +/** + * Get the type of opt based on the number of `-` at the beginning and the + * _validity_ of the key name. + * + * A valid key name must start with an alphabetical character. + * + * Returns: 1 if s has one `-` at the beginning, that is, "-keyName". + * 2 if s has two `-` at the beginning, that is, "--keyName". + * 0 otherwise. That is, if s has no `-` at the beginning, or has more + * than 2 at the beginning ("---keyName", "----keyName", ...), or the + * keyName is invalid (the first character is not an alphabetical + * character). + */ +size_t getOptType(char *s) { + if (!s || strlen(s) <= 1) + return 0; + + if (s[0] == '-') { + if (isalpha(s[1])) + return 1; + else if (s[1] == '-') + return isalpha(s[2]) ? 2 : 0; + } + + return 0; +} + +/** + * Parse the opt at a given index, and put it into the opts maps. + * + * An opt can has the following form: + * 1) -keyName=value or --keyName=value (ex. -n=10 --test-count=20) + * 2) -keyName value or --keyName value (ex. -n 10 --test-count 20) + * 3) -kNumval or --kNumval (ex. -n10 --t20) + * 4) -boolProperty or --boolProperty (ex. -sorted --tree-only) + * + * Only the second form consumes 2 arguments. The other consumes only 1 + * argument. + * + * In the third form, the key is a single character, and after the key is the + * value. The value _should_ be a number. + * + * In the forth form, the value is true. + * + * Params: + * - argc and argv: the number of command line arguments and the command line + * arguments themselves. + * - index: the starting index of the opts. + * - opts: the map containing the resulting opt. + * + * Returns: the number of consumed arguments to parse the opt. + * 0 if there is no arguments to parse. + * + * Algorithm details: + * TODO. Please refer to the implementation to see how the code handles the 3rd and 4th forms separately. + */ +size_t parseOpt(size_t argc, char *argv[], size_t index, std::map &opts) { + if (index >= argc) + return 0; + + size_t type = getOptType(argv[index]), inc = 1; + if (type > 0) { + std::string key(argv[index] + type), val; + size_t sep = key.find('='); + if (sep != std::string::npos) { + val = key.substr(sep + 1); + key = key.substr(0, sep); + } else { + if (index + 1 < argc && getOptType(argv[index + 1]) == 0) { + val = argv[index + 1]; + inc = 2; + } else { + if (key.length() > 1 && isdigit(key[1])) { + val = key.substr(1); + key = key.substr(0, 1); + } else { + val = "true"; + } + } + } + opts[key].value = val; + } else { + return inc; + } + + return inc; +} + +/** + * Global list containing all the arguments in the order given in the command line. + */ +std::vector __testlib_argv; + +/** + * Global dictionary containing all the parsed opts. + */ +std::map __testlib_opts; + +/** + * Whether automatic no unused opts ensurement should be done. This flag will + * be turned on when `has_opt` or `opt(key, default_value)` is called. + * + * The automatic ensurement can be suppressed when + * __testlib_ensureNoUnusedOptsSuppressed is true. + */ +bool __testlib_ensureNoUnusedOptsFlag = false; + +/** + * Suppress no unused opts automatic ensurement. Can be set to true with + * `suppressEnsureNoUnusedOpts()`. + */ +bool __testlib_ensureNoUnusedOptsSuppressed = false; + +/** + * Parse command line arguments into opts. + * The results are stored into __testlib_argv and __testlib_opts. + */ +void prepareOpts(int argc, char *argv[]) { + if (argc <= 0) + __testlib_fail("Opts: expected argc>=0 but found " + toString(argc)); + size_t n = static_cast(argc); // NOLINT(hicpp-use-auto,modernize-use-auto) + __testlib_opts = std::map(); + for (size_t index = 1; index < n; index += parseOpt(n, argv, index, __testlib_opts)); + __testlib_argv = std::vector(n); + for (size_t index = 0; index < n; index++) + __testlib_argv[index] = argv[index]; +} + +/** + * An utility function to get the argument with a given index. This function + * also print a readable message when no arguments are found. + */ +std::string __testlib_indexToArgv(int index) { + if (index < 0 || index >= int(__testlib_argv.size())) + __testlib_fail("Opts: index '" + toString(index) + "' is out of range [0," + + toString(__testlib_argv.size()) + ")"); + return __testlib_argv[size_t(index)]; +} + +/** + * An utility function to get the opt with a given key . This function + * also print a readable message when no opts are found. + */ +std::string __testlib_keyToOpts(const std::string &key) { + auto it = __testlib_opts.find(key); + if (it == __testlib_opts.end()) + __testlib_fail("Opts: unknown key '" + compress(key) + "'"); + it->second.used = true; + return it->second.value; +} + +template +T optValueToIntegral(const std::string &s, bool nonnegative); + +long double optValueToLongDouble(const std::string &s); + +std::string parseExponentialOptValue(const std::string &s) { + size_t pos = std::string::npos; + for (size_t i = 0; i < s.length(); i++) + if (s[i] == 'e' || s[i] == 'E') { + if (pos != std::string::npos) + __testlib_fail("Opts: expected typical exponential notation but '" + compress(s) + "' found"); + pos = i; + } + if (pos == std::string::npos) + return s; + std::string e = s.substr(pos + 1); + if (!e.empty() && e[0] == '+') + e = e.substr(1); + if (e.empty()) + __testlib_fail("Opts: expected typical exponential notation but '" + compress(s) + "' found"); + if (e.length() > 20) + __testlib_fail("Opts: expected typical exponential notation but '" + compress(s) + "' found"); + int ne = optValueToIntegral(e, false); + std::string num = s.substr(0, pos); + if (num.length() > 20) + __testlib_fail("Opts: expected typical exponential notation but '" + compress(s) + "' found"); + if (!num.empty() && num[0] == '+') + num = num.substr(1); + optValueToLongDouble(num); + bool minus = false; + if (num[0] == '-') { + minus = true; + num = num.substr(1); + } + for (int i = 0; i < +ne; i++) { + size_t sep = num.find('.'); + if (sep == std::string::npos) + num += '0'; + else { + if (sep + 1 == num.length()) + num[sep] = '0'; + else + std::swap(num[sep], num[sep + 1]); + } + } + for (int i = 0; i < -ne; i++) { + size_t sep = num.find('.'); + if (sep == std::string::npos) + num.insert(num.begin() + int(num.length()) - 1, '.'); + else { + if (sep == 0) + num.insert(num.begin() + 1, '0'); + else + std::swap(num[sep - 1], num[sep]); + } + } + while (!num.empty() && num[0] == '0') + num = num.substr(1); + while (num.find('.') != std::string::npos && num.back() == '0') + num = num.substr(0, num.length() - 1); + if (!num.empty() && num.back() == '.') + num = num.substr(0, num.length() - 1); + if ((!num.empty() && num[0] == '.') || num.empty()) + num.insert(num.begin(), '0'); + return (minus ? "-" : "") + num; +} + +template +T optValueToIntegral(const std::string &s_, bool nonnegative) { + std::string s(parseExponentialOptValue(s_)); + if (s.empty()) + __testlib_fail("Opts: expected integer but '" + compress(s_) + "' found"); + T value = 0; + long double about = 0.0; + signed char sign = +1; + size_t pos = 0; + if (s[pos] == '-') { + if (nonnegative) + __testlib_fail("Opts: expected non-negative integer but '" + compress(s_) + "' found"); + sign = -1; + pos++; + } + for (size_t i = pos; i < s.length(); i++) { + if (s[i] < '0' || s[i] > '9') + __testlib_fail("Opts: expected integer but '" + compress(s_) + "' found"); + value = value * 10 + s[i] - '0'; + about = about * 10 + s[i] - '0'; + } + value *= sign; + about *= sign; + if (fabsl(value - about) > 0.1) + __testlib_fail("Opts: integer overflow: expected integer but '" + compress(s_) + "' found"); + return value; +} + +long double optValueToLongDouble(const std::string &s_) { + std::string s(parseExponentialOptValue(s_)); + if (s.empty()) + __testlib_fail("Opts: expected float number but '" + compress(s_) + "' found"); + long double value = 0.0; + signed char sign = +1; + size_t pos = 0; + if (s[pos] == '-') { + sign = -1; + pos++; + } + bool period = false; + long double mul = 1.0; + for (size_t i = pos; i < s.length(); i++) { + if (s[i] == '.') { + if (period) + __testlib_fail("Opts: expected float number but '" + compress(s_) + "' found"); + else { + period = true; + continue; + } + } + if (period) + mul *= 10.0; + if (s[i] < '0' || s[i] > '9') + __testlib_fail("Opts: expected float number but '" + compress(s_) + "' found"); + if (period) + value += (s[i] - '0') / mul; + else + value = value * 10 + s[i] - '0'; + } + value *= sign; + return value; +} + +/** + * Return true if there is an opt with a given key. + * + * By calling this function, automatic ensurement for no unused opts will be + * done when the program is finalized. Call suppressEnsureNoUnusedOpts() to + * turn it off. + */ +bool has_opt(const std::string &key) { + __testlib_ensureNoUnusedOptsFlag = true; + return __testlib_opts.count(key) != 0; +} + +/* About the followings part for opt with 2 and 3 arguments. + * + * To parse the argv/opts correctly for a give type (integer, floating point or + * string), some meta programming must be done to determine the type of + * the type, and use the correct parsing function accordingly. + * + * The pseudo algorithm for determining the type of T and parse it accordingly + * is as follows: + * + * if (T is integral type) { + * if (T is unsigned) { + * parse the argv/opt as an **unsigned integer** of type T. + * } else { + * parse the argv/opt as an **signed integer** of type T. + * } else { + * if (T is floating point type) { + * parse the argv/opt as an **floating point** of type T. + * } else { + * // T should be std::string + * just the raw content of the argv/opts. + * } + * } + * + * To help with meta programming, some `opt` function with 2 or 3 arguments are + * defined. + * + * Opt with 3 arguments: T opt(true/false is_integral, true/false is_unsigned, index/key) + * + * + The first argument is for determining whether the type T is an integral + * type. That is, the result of std::is_integral() should be passed to + * this argument. When false, the type _should_ be either floating point or a + * std::string. + * + * + The second argument is for determining whether the signedness of the type + * T (if it is unsigned or signed). That is, the result of + * std::is_unsigned() should be passed to this argument. This argument can + * be ignored if the first one is false, because it only applies to integer. + * + * Opt with 2 arguments: T opt(true/false is_floating_point, index/key) + * + The first argument is for determining whether the type T is a floating + * point type. That is, the result of std::is_floating_point() should be + * passed to this argument. When false, the type _should_ be a std::string. + */ + +template +T opt(std::false_type is_floating_point, int index); + +template<> +std::string opt(std::false_type /*is_floating_point*/, int index) { + return __testlib_indexToArgv(index); +} + +template +T opt(std::true_type /*is_floating_point*/, int index) { + return T(optValueToLongDouble(__testlib_indexToArgv(index))); +} + +template +T opt(std::false_type /*is_integral*/, U /*is_unsigned*/, int index) { + return opt(std::is_floating_point(), index); +} + +template +T opt(std::true_type /*is_integral*/, std::false_type /*is_unsigned*/, int index) { + return optValueToIntegral(__testlib_indexToArgv(index), false); +} + +template +T opt(std::true_type /*is_integral*/, std::true_type /*is_unsigned*/, int index) { + return optValueToIntegral(__testlib_indexToArgv(index), true); +} + +template<> +bool opt(std::true_type /*is_integral*/, std::true_type /*is_unsigned*/, int index) { + std::string value = __testlib_indexToArgv(index); + if (value == "true" || value == "1") + return true; + if (value == "false" || value == "0") + return false; + __testlib_fail("Opts: opt by index '" + toString(index) + "': expected bool true/false or 0/1 but '" + + compress(value) + "' found"); +} + +/** + * Return the parsed argv by a given index. + */ +template +T opt(int index) { + return opt(std::is_integral(), std::is_unsigned(), index); +} + +/** + * Return the raw string value of an argv by a given index. + */ +std::string opt(int index) { + return opt(index); +} + +/** + * Return the parsed argv by a given index. If the index is bigger than + * the number of argv, return the given default_value. + */ +template +T opt(int index, const T &default_value) { + if (index >= int(__testlib_argv.size())) { + return default_value; + } + return opt(index); +} + +/** + * Return the raw string value of an argv by a given index. If the index is + * bigger than the number of argv, return the given default_value. + */ +std::string opt(int index, const std::string &default_value) { + return opt(index, default_value); +} + +template +T opt(std::false_type is_floating_point, const std::string &key); + +template<> +std::string opt(std::false_type /*is_floating_point*/, const std::string &key) { + return __testlib_keyToOpts(key); +} + +template +T opt(std::true_type /*is_integral*/, const std::string &key) { + return T(optValueToLongDouble(__testlib_keyToOpts(key))); +} + +template +T opt(std::false_type /*is_integral*/, U, const std::string &key) { + return opt(std::is_floating_point(), key); +} + +template +T opt(std::true_type /*is_integral*/, std::false_type /*is_unsigned*/, const std::string &key) { + return optValueToIntegral(__testlib_keyToOpts(key), false); +} + +template +T opt(std::true_type /*is_integral*/, std::true_type /*is_unsigned*/, const std::string &key) { + return optValueToIntegral(__testlib_keyToOpts(key), true); +} + +template<> +bool opt(std::true_type /*is_integral*/, std::true_type /*is_unsigned*/, const std::string &key) { + if (!has_opt(key)) + return false; + std::string value = __testlib_keyToOpts(key); + if (value == "true" || value == "1") + return true; + if (value == "false" || value == "0") + return false; + __testlib_fail("Opts: key '" + compress(key) + "': expected bool true/false or 0/1 but '" + + compress(value) + "' found"); +} + +/** + * Return the parsed opt by a given key. + */ +template +T opt(const std::string &key) { + return opt(std::is_integral(), std::is_unsigned(), key); +} + +/** + * Return the raw string value of an opt by a given key + */ +std::string opt(const std::string &key) { + return opt(key); +} + +/* Scorer started. */ + +enum TestResultVerdict { + SKIPPED, + OK, + WRONG_ANSWER, + RUNTIME_ERROR, + TIME_LIMIT_EXCEEDED, + IDLENESS_LIMIT_EXCEEDED, + MEMORY_LIMIT_EXCEEDED, + COMPILATION_ERROR, + CRASHED, + FAILED +}; + +std::string serializeVerdict(TestResultVerdict verdict) { + switch (verdict) { + case SKIPPED: return "SKIPPED"; + case OK: return "OK"; + case WRONG_ANSWER: return "WRONG_ANSWER"; + case RUNTIME_ERROR: return "RUNTIME_ERROR"; + case TIME_LIMIT_EXCEEDED: return "TIME_LIMIT_EXCEEDED"; + case IDLENESS_LIMIT_EXCEEDED: return "IDLENESS_LIMIT_EXCEEDED"; + case MEMORY_LIMIT_EXCEEDED: return "MEMORY_LIMIT_EXCEEDED"; + case COMPILATION_ERROR: return "COMPILATION_ERROR"; + case CRASHED: return "CRASHED"; + case FAILED: return "FAILED"; + } + throw "Unexpected verdict"; +} + +TestResultVerdict deserializeTestResultVerdict(std::string s) { + if (s == "SKIPPED") + return SKIPPED; + else if (s == "OK") + return OK; + else if (s == "WRONG_ANSWER") + return WRONG_ANSWER; + else if (s == "RUNTIME_ERROR") + return RUNTIME_ERROR; + else if (s == "TIME_LIMIT_EXCEEDED") + return TIME_LIMIT_EXCEEDED; + else if (s == "IDLENESS_LIMIT_EXCEEDED") + return IDLENESS_LIMIT_EXCEEDED; + else if (s == "MEMORY_LIMIT_EXCEEDED") + return MEMORY_LIMIT_EXCEEDED; + else if (s == "COMPILATION_ERROR") + return COMPILATION_ERROR; + else if (s == "CRASHED") + return CRASHED; + else if (s == "FAILED") + return FAILED; + ensuref(false, "Unexpected serialized TestResultVerdict"); + // No return actually. + return FAILED; +} + +struct TestResult { + int testIndex; + std::string testset; + std::string group; + TestResultVerdict verdict; + double points; + long long timeConsumed; + long long memoryConsumed; + std::string input; + std::string output; + std::string answer; + int exitCode; + std::string checkerComment; +}; + +std::string serializePoints(double points) { + if (std::isnan(points)) + return ""; + else { + char c[64]; + sprintf(c, "%.03lf", points); + return c; + } +} + +double deserializePoints(std::string s) { + if (s.empty()) + return std::numeric_limits::quiet_NaN(); + else { + double result; + ensuref(sscanf(s.c_str(), "%lf", &result) == 1, "Invalid serialized points"); + return result; + } +} + +std::string escapeTestResultString(std::string s) { + std::string result; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == '\r') + continue; + if (s[i] == '\n') { + result += "\\n"; + continue; + } + if (s[i] == '\\' || s[i] == ';') + result += '\\'; + result += s[i]; + } + return result; +} + +std::string unescapeTestResultString(std::string s) { + std::string result; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == '\\' && i + 1 < s.length()) { + if (s[i + 1] == 'n') { + result += '\n'; + i++; + continue; + } else if (s[i + 1] == ';' || s[i + 1] == '\\') { + result += s[i + 1]; + i++; + continue; + } + } + result += s[i]; + } + return result; +} + +std::string serializeTestResult(TestResult tr) { + std::string result; + result += std::to_string(tr.testIndex); + result += ";"; + result += escapeTestResultString(tr.testset); + result += ";"; + result += escapeTestResultString(tr.group); + result += ";"; + result += serializeVerdict(tr.verdict); + result += ";"; + result += serializePoints(tr.points); + result += ";"; + result += std::to_string(tr.timeConsumed); + result += ";"; + result += std::to_string(tr.memoryConsumed); + result += ";"; + result += escapeTestResultString(tr.input); + result += ";"; + result += escapeTestResultString(tr.output); + result += ";"; + result += escapeTestResultString(tr.answer); + result += ";"; + result += std::to_string(tr.exitCode); + result += ";"; + result += escapeTestResultString(tr.checkerComment); + return result; +} + +TestResult deserializeTestResult(std::string s) { + std::vector items; + std::string t; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == '\\') { + t += s[i]; + if (i + 1 < s.length()) + t += s[i + 1]; + i++; + continue; + } else { + if (s[i] == ';') { + items.push_back(t); + t = ""; + } else + t += s[i]; + } + } + items.push_back(t); + + ensuref(items.size() == 12, "Invalid TestResult serialization: expected exactly 12 items"); + + TestResult tr; + size_t pos = 0; + tr.testIndex = stoi(items[pos++]); + tr.testset = unescapeTestResultString(items[pos++]); + tr.group = unescapeTestResultString(items[pos++]); + tr.verdict = deserializeTestResultVerdict(items[pos++]); + tr.points = deserializePoints(items[pos++]); + tr.timeConsumed = stoll(items[pos++]); + tr.memoryConsumed = stoll(items[pos++]); + tr.input = unescapeTestResultString(items[pos++]); + tr.output = unescapeTestResultString(items[pos++]); + tr.answer = unescapeTestResultString(items[pos++]); + tr.exitCode = stoi(items[pos++]); + tr.checkerComment = unescapeTestResultString(items[pos++]); + + return tr; +} + +std::vector readTestResults(std::string fileName) { + std::ifstream stream; + stream.open(fileName.c_str(), std::ios::in); + ensuref(stream.is_open(), "Can't read test results file '%s'", fileName.c_str()); + std::vector result; + std::string line; + while (getline(stream, line)) + if (!line.empty()) + result.push_back(deserializeTestResult(line)); + stream.close(); + return result; +} + +std::function)> __testlib_scorer; + +struct TestlibScorerGuard { + ~TestlibScorerGuard() { + if (testlibMode == _scorer) { + std::vector testResults; + while (!inf.eof()) { + std::string line = inf.readLine(); + if (!line.empty()) + testResults.push_back(deserializeTestResult(line)); + } + inf.readEof(); + printf("%.3f\n", __testlib_scorer(testResults)); + } + } +} __testlib_scorer_guard; + +void registerScorer(int argc, char *argv[], std::function)> scorer) { + /* Supress unused. */ + (void)(argc), (void)(argv); + + __testlib_ensuresPreconditions(); + + testlibMode = _scorer; + __testlib_set_binary(stdin); + + inf.init(stdin, _input); + inf.strict = false; + + __testlib_scorer = scorer; +} + +/* Scorer ended. */ + +/** + * Return the parsed opt by a given key. If no opts with the given key are + * found, return the given default_value. + * + * By calling this function, automatic ensurement for no unused opts will be + * done when the program is finalized. Call suppressEnsureNoUnusedOpts() to + * turn it off. + */ +template +T opt(const std::string &key, const T &default_value) { + if (!has_opt(key)) { + return default_value; + } + return opt(key); +} + +/** + * Return the raw string value of an opt by a given key. If no opts with the + * given key are found, return the given default_value. + * + * By calling this function, automatic ensurement for no unused opts will be + * done when the program is finalized. Call suppressEnsureNoUnusedOpts() to + * turn it off. + */ +std::string opt(const std::string &key, const std::string &default_value) { + return opt(key, default_value); +} + +/** + * Check if all opts are used. If not, __testlib_fail is called. + * Should be used after calling all opt() function calls. + * + * This function is useful when opt() with default_value for checking typos + * in the opt's key. + */ +void ensureNoUnusedOpts() { + for (const auto &opt: __testlib_opts) { + if (!opt.second.used) { + __testlib_fail(format("Opts: unused key '%s'", compress(opt.first).c_str())); + } + } +} + +void suppressEnsureNoUnusedOpts() { + __testlib_ensureNoUnusedOptsSuppressed = true; +} + +void TestlibFinalizeGuard::autoEnsureNoUnusedOpts() { + if (__testlib_ensureNoUnusedOptsFlag && !__testlib_ensureNoUnusedOptsSuppressed) { + ensureNoUnusedOpts(); + } +} + +TestlibFinalizeGuard testlibFinalizeGuard; + +#endif +#endif diff --git a/edit-distance/src/validator.cpp b/edit-distance/src/validator.cpp new file mode 100644 index 0000000..ea7646d --- /dev/null +++ b/edit-distance/src/validator.cpp @@ -0,0 +1,19 @@ +#include "testlib.h" +#include + +using namespace std; + + +int main(int argc, char* argv[]) { + registerValidation(argc, argv); + int n = inf.readInt(1, 500, "n"); + inf.readSpace(); + int m = inf.readInt(1, 500, "m"); + inf.readEoln(); + inf.readToken("[a-z]{" + to_string(n) + "}", "s1"); + inf.readSpace(); + inf.readToken("[a-z]{" + to_string(m) + "}", "s2"); + inf.readEoln(); + inf.readEof(); + return 0; +} \ No newline at end of file diff --git a/edit-distance/statement/description.tex b/edit-distance/statement/description.tex new file mode 100644 index 0000000..5f1da72 --- /dev/null +++ b/edit-distance/statement/description.tex @@ -0,0 +1,11 @@ +O problema consiste em determinar o \textbf{menor número de operações} necessárias para transformar uma string em outra. + +As operações permitidas são as seguintes: + +\begin{itemize} + \item \textbf{Inserção}: inserir um caractere em qualquer posição; + \item \textbf{Remoção}: remover um caractere de qualquer posição; + \item \textbf{Substituição}: substituir um caractere por outro. +\end{itemize} + +O objetivo é calcular o menor custo possível para converter completamente uma dada string inicial em uma string final, utilizando apenas essas operações. \ No newline at end of file diff --git a/edit-distance/statement/input.tex b/edit-distance/statement/input.tex new file mode 100644 index 0000000..7bdfb40 --- /dev/null +++ b/edit-distance/statement/input.tex @@ -0,0 +1,6 @@ +A entrada consiste de duas linhas: + +\begin{itemize} + \item A primeira linha contém dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 500 \)), representando os tamanhos das strings. + \item A segunda linha contém duas strings \( s_1 \) e \( s_2 \), ambas compostas apenas por letras minúsculas e com tamanhos exatos \( n \) e \( m \), respectivamente. +\end{itemize} diff --git a/edit-distance/statement/notes.tex b/edit-distance/statement/notes.tex new file mode 100644 index 0000000..e69de29 diff --git a/edit-distance/statement/output.tex b/edit-distance/statement/output.tex new file mode 100644 index 0000000..44bf03c --- /dev/null +++ b/edit-distance/statement/output.tex @@ -0,0 +1 @@ +Imprima um único inteiro representando o \textbf{menor número de operações} necessárias para transformar \( s_1 \) em \( s_2 \). diff --git a/edit-distance/statement/preamble.tex b/edit-distance/statement/preamble.tex new file mode 100644 index 0000000..e69de29 diff --git a/edit-distance/statement/tutorial.tex b/edit-distance/statement/tutorial.tex new file mode 100644 index 0000000..e69de29