CXX = g++ SRC_DIR = src GEN_DIR = generator VAL_DIR = validator INC_DIR = include CHK_DIR = checker BUILD_DIR = build BUILD_TARGET_DIR = $(BUILD_DIR)/target BUILD_GEN_DIR = $(BUILD_DIR)/gen BUILD_VAL_DIR = $(BUILD_DIR)/val BUILD_CHK_DIR = $(BUILD_DIR)/chk CXXFLAGS = -Wall -O2 -std=c++2a -I$(INC_DIR) BSB_EXE = $(BUILD_TARGET_DIR)/bsb DIJK_EXE = $(BUILD_TARGET_DIR)/dijk GEN1_EXE = $(BUILD_GEN_DIR)/gen1 GEN2_EXE = $(BUILD_GEN_DIR)/gen2 GENS = $(GEN1_EXE) $(GEN2_EXE) GEN_DEFAULT = $(GEN1_EXE) VAL_EXE = $(BUILD_VAL_DIR)/validator CHK_EXE = $(BUILD_CHK_DIR)/checker IN = $(BUILD_DIR)/input.txt OUT_DIJK = $(BUILD_DIR)/dijk.out OUT_BSB = $(BUILD_DIR)/bsb.out TEST_COUNT = 100 .PHONY: all all: $(BSB_EXE) $(DIJK_EXE) $(GEN1_EXE) $(GEN2_EXE) $(VAL_EXE) $(CHK_EXE) @echo "All executables compiled in $(BUILD_DIR)/" $(BUILD_TARGET_DIR)/%: $(SRC_DIR)/%/main.cpp | $(BUILD_TARGET_DIR) @echo "Compiling Solution $< -> $@" $(CXX) $(CXXFLAGS) -o $@ $< $(BUILD_GEN_DIR)/%: $(GEN_DIR)/%.cpp | $(BUILD_GEN_DIR) @echo "Compiling Generator $< -> $@" $(CXX) $(CXXFLAGS) -o $@ $< $(BUILD_VAL_DIR)/%: $(VAL_DIR)/%.cpp | $(BUILD_VAL_DIR) @echo "Compiling Validator $< -> $@" $(CXX) $(CXXFLAGS) -o $@ $< $(BUILD_CHK_DIR)/%: $(CHK_DIR)/%.cpp | $(BUILD_CHK_DIR) @echo "Compiling Checker $< -> $@" $(CXX) $(CXXFLAGS) -o $@ $< $(BUILD_DIR): @echo "Creating directory: $@" @mkdir -p $@ $(BUILD_TARGET_DIR): | $(BUILD_DIR) @echo "Creating directory: $@" @mkdir -p $@ $(BUILD_GEN_DIR): | $(BUILD_DIR) @echo "Creating directory: $@" @mkdir -p $@ $(BUILD_VAL_DIR): | $(BUILD_DIR) @echo "Creating directory: $@" @mkdir -p $@ $(BUILD_CHK_DIR): | $(BUILD_DIR) @echo "Creating directory: $@" @mkdir -p $@ .PHONY: gen1 gen1: $(GENS) @echo "--- gen1 : Generating 1 test case ---" @SEED=$$(export LC_ALL=C; cat /dev/urandom | tr -cd '[[:graph:]]' | head -c 32); \ echo "./$(GEN1_EXE) -N $(N) -pm $(pm) $$SEED | tee $(IN)"; \ ./$(GEN1_EXE) -N $(N) -pm $(pm) $$SEED | tee $(IN) .PHONY: gen1-silence gen1-silence: $(GENS) @echo "--- gen1 : Generating 1 test case ---" @SEED=$$(export LC_ALL=C; cat /dev/urandom | tr -cd '[[:graph:]]' | head -c 32); \ echo "./$(GEN1_EXE) -N $(N) -M $(M) $$SEED > $(IN)"; \ ./$(GEN1_EXE) -N $(N) -M $(M) $$SEED > $(IN) .PHONY: val val: $(VAL_EXE) | gen1-silence @echo "--- Validating test case $(IN)..." # @./$(VAL_EXE) < $(IN) @echo "Validator OK." .PHONY: check check: all val @echo "--- Running: $(DIJK_EXE)" @time ./$(DIJK_EXE) < $(IN) > $(OUT_DIJK) @echo "--- Running: $(BSB_EXE)" @time ./$(BSB_EXE) < $(IN) > $(OUT_BSB) @echo "--- Comparing Outputs (using $(CHK_EXE)) ---" @./$(CHK_EXE) $(IN) $(OUT_DIJK) $(OUT_BSB) || ( \ echo "WA (Wrong Answer): Checker found an issue!" && \ echo "Input is saved to $(IN)" && \ exit 1 \ ) @echo "OK: Outputs match!" # .PHONY: check # check: all val # @echo "--- Running Solution: $(BSB_EXE)" # @./$(BSB_EXE) < $(IN) > $(OUT_SOL) # @echo "--- Running Brute Force: $(DIJK_EXE)" # @./$(DIJK_EXE) < $(IN) > $(OUT_BRUTE) # @echo "--- Comparing Outputs ---" # @diff -w $(OUT_SOL) $(OUT_BRUTE) || ( \ # echo "WA (Wrong Answer): Outputs differ!" && \ # echo "Input is saved to $(IN)" && \ # exit 1 \ # ) # @echo "OK: Outputs match!" .PHONY: test test: all @echo "--- Running $(TEST_COUNT) tests ---" @for i in {1..$(TEST_COUNT)}; do \ SEED=$$(export LC_ALL=C; cat /dev/urandom | tr -cd '[[:graph:]]' | head -c 32); \ printf "Test %4d (Seed: %s): " "$$i" "$$SEED"; \ ./$(GEN_DEFAULT) -N $(N) -M $(M) $$SEED > $(IN); \ printf "(GEN) "; \ printf "DIJK: "; \ ( TIMEFORMAT=%R; time ./$(DIJK_EXE) < $(IN) > $(OUT_DIJK) ) 2>&1 | tr '\n' ' ' ; \ printf "BSB: "; \ ( TIMEFORMAT=%R; time ./$(BSB_EXE) < $(IN) > $(OUT_BSB) ) 2>&1 | tr '\n' ' ' ; \ printf "CHK: "; \ ( ./$(CHK_EXE) $(IN) $(OUT_BSB) $(OUT_DIJK) > /dev/null ) 2>&1 || { printf "\nWA! (Seed: %s)\n" "$$SEED"; echo "Input saved to $(IN)"; exit 1; }; \ done @echo "--- All $(TEST_COUNT) tests passed! ---" # ./$(VAL_EXE) < $(IN) > /dev/null || { echo "Validator Error! (Seed: $$SEED)"; echo "Input saved to $(IN)"; break; }; .PHONY: bench bench: $(BSB_EXE) val @echo "--- Benchmarking $(BSB_EXE) with $(IN) ---" @time ./$(BSB_EXE) < $(IN) > $(OUT_BSB) .PHONY: format format: @echo "--- Formatting all C/C++ files ---" @find $(SRC_DIR) $(GEN_DIR) $(VAL_DIR) $(CHK_DIR) $(INC_DIR) -type f \( -name "*.cpp" -o -name "*.c" -o -name "*.hpp" -o -name "*.h" \) -print0 | xargs -0 clang-format -i @echo "Formatting complete." .PHONY: clean clean: @echo "Cleaning up $(BUILD_DIR)/..." @rm -r build