1
0
Fork 0

Read from stdin when no input file specified

This commit is contained in:
Joris van Rantwijk 2023-02-19 19:44:06 +01:00
parent 83d9e37db6
commit 37aa0c605b
1 changed files with 24 additions and 25 deletions

View File

@ -9,6 +9,7 @@ from __future__ import annotations
import sys import sys
import argparse import argparse
import math import math
import os
import os.path import os.path
from typing import Optional, TextIO from typing import Optional, TextIO
@ -30,8 +31,9 @@ def read_dimacs_graph(f: TextIO) -> list[tuple[int, int, int|float]]:
edges: list[tuple[int, int, float]] = [] edges: list[tuple[int, int, float]] = []
for s in f: for line in f:
words = s.strip().split() s = line.strip()
words = s.split()
if not words[0]: if not words[0]:
# Skip empty line. # Skip empty line.
@ -45,7 +47,7 @@ def read_dimacs_graph(f: TextIO) -> list[tuple[int, int, int|float]]:
# Handle "problem" line. # Handle "problem" line.
if len(words) != 4: if len(words) != 4:
raise ValueError( raise ValueError(
f"Expecting DIMACS edge format but got {s.strip()!r}") f"Expecting DIMACS edge format but got {s!r}")
if words[1] != "edge": if words[1] != "edge":
raise ValueError( raise ValueError(
f"Expecting DIMACS edge format but got {words[1]!r}") f"Expecting DIMACS edge format but got {words[1]!r}")
@ -53,11 +55,13 @@ def read_dimacs_graph(f: TextIO) -> list[tuple[int, int, int|float]]:
elif words[0] == "e": elif words[0] == "e":
# Handle "edge" line. # Handle "edge" line.
if len(words) != 4: if len(words) != 4:
raise ValueError(f"Expecting edge but got {s.strip()!r}") raise ValueError(f"Expecting edge but got {s!r}")
x = int(words[1]) x = int(words[1])
y = int(words[2]) y = int(words[2])
if (x < 1) or (y < 1):
raise ValueError(f"Invalid vertex index {s!r}")
w = parse_int_or_float(words[3]) w = parse_int_or_float(words[3])
edges.append((x, y, w)) edges.append((x - 1, y - 1, w))
else: else:
raise ValueError(f"Unknown line type {words[0]!r}") raise ValueError(f"Unknown line type {words[0]!r}")
@ -89,8 +93,9 @@ def read_dimacs_matching(
weight: int|float = 0 weight: int|float = 0
pairs: list[tuple[int, int]] = [] pairs: list[tuple[int, int]] = []
for s in f: for line in f:
words = s.strip().split() s = line.strip()
words = s.split()
if not words[0]: if not words[0]:
# Skip empty line. # Skip empty line.
@ -104,7 +109,7 @@ def read_dimacs_matching(
# Handle "solution" line. # Handle "solution" line.
if len(words) != 2: if len(words) != 2:
raise ValueError( raise ValueError(
f"Expecting solution line but got {s.strip()}") f"Expecting solution line but got {s!r}")
if have_weight: if have_weight:
raise ValueError("Duplicate solution line") raise ValueError("Duplicate solution line")
have_weight = True have_weight = True
@ -114,10 +119,12 @@ def read_dimacs_matching(
# Handle "matching" line. # Handle "matching" line.
if len(words) != 3: if len(words) != 3:
raise ValueError( raise ValueError(
f"Expecting matched edge but got {s.strip()}") f"Expecting matched edge but got {s!r}")
x = int(words[1]) x = int(words[1])
y = int(words[2]) y = int(words[2])
pairs.append((x, y)) if (x < 1) or (y < 1):
raise ValueError(f"Invalid vertex index {s!r}")
pairs.append((x - 1, y - 1))
else: else:
raise ValueError(f"Unknown line type {words[0]!r}") raise ValueError(f"Unknown line type {words[0]!r}")
@ -152,7 +159,7 @@ def write_dimacs_matching(
print("s", f"{weight:.12g}", file=f) print("s", f"{weight:.12g}", file=f)
for (x, y) in pairs: for (x, y) in pairs:
print("m", x, y, file=f) print("m", x + 1, y + 1, file=f)
def write_dimacs_matching_file( def write_dimacs_matching_file(
@ -324,9 +331,6 @@ def main() -> int:
parser.description = ( parser.description = (
"Calculate maximum weighted matching of graphs in DIMACS format.") "Calculate maximum weighted matching of graphs in DIMACS format.")
parser.add_argument("--stdin",
action="store_true",
help="read graph from stdin")
parser.add_argument("--verify", parser.add_argument("--verify",
action="store_true", action="store_true",
help="verify existing output file(s)") help="verify existing output file(s)")
@ -344,24 +348,19 @@ def main() -> int:
help="directory to write output") help="directory to write output")
parser.add_argument("input", parser.add_argument("input",
nargs="*", nargs="*",
help="input file(s)") help="input file(s); leave empty to read from stdin")
args = parser.parse_args() args = parser.parse_args()
if args.stdin and args.verify: if (not args.input) and os.isatty(sys.stdin.fileno()):
print("ERROR: Can not verify when reading from stdin", print("ERROR: Expecting input from stdin but stdin is a terminal",
file=sys.stderr) file=sys.stderr)
return 1
if (not args.stdin) and (not args.input):
parser.print_help(sys.stderr)
print(file=sys.stderr) print(file=sys.stderr)
print("ERROR: Specify either --stdin or at least one input file", parser.print_help(sys.stderr)
file=sys.stderr)
return 1 return 1
if args.stdin and args.input: if (not args.input) and args.verify:
print("ERROR: Specify either --stdin or input files, not both", print("ERROR: Can not verify when reading from stdin",
file=sys.stderr) file=sys.stderr)
return 1 return 1