// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> // SPDX-License-Identifier: GPL-3.0-or-later package dk.abcdefghijklmnopqrstuvxyzæøå.bachelorizer.model; import java.util.Collection; import java.util.Set; import com.example.portfolio3.AdjListGraph; import com.example.portfolio3.Graph; import com.example.portfolio3.GraphAlgorithms; import com.example.portfolio3.MatrixGraph; import com.example.portfolio3.Vertex; /// Combi - static sample dataset of course combinations /// /// Slurps and parses data from upstream-provided comma-separated file. /// /// @version 0.0.1 /// @see <https://moodle.ruc.dk/mod/assign/view.php?id=523186> public final class Combi { /// data about combinations as a Graph private Graph g; /// Default constructor /// /// @param path path to data file private Combi(final String path) { // read into temporary graph to resolve vertice count // // use Adjacency List Representation: // * cheap to bootstrap (done once) // * simple to count vertices (done once): O(1) Graph _g = new AdjListGraph(); GraphAlgorithms.readGraph(_g, path); Integer _vertice_count = _g.vertices().size(); // read into final graph // // use Adjacency Matrix Representation: // * expensive to bootstrap (done once) // * simple to add edges but needs vertice count // * simple to get edges (done repeatedly): O(1) // // TODO: avoid reading and parsing file twice Graph g = new MatrixGraph(_vertice_count); GraphAlgorithms.readGraph(g, path); // ensure the graph is connected isConnected(g); GraphAlgorithms.printGraph(g); // release temporary variables for garbage collection _g = null; _vertice_count = null; } /// JVM entry point /// /// @param args command-line arguments public static void main(final String[] args) { // first argument, if provided, is the data file path; // else use upstream named file in current directory. String path = (args.length > 0) ? args[0] : "combi.txt"; Combi combi = new Combi(path); } /// utility function to check that a graph is connected /// /// If check fails, throw an unchecked exception, /// since it occurs at runtime and is unrecoverable. /// /// Time complexity of the operation is O(n²) /// where n is the amount of vertices, /// since visitDepthFirst() recurses out-edges of all vertices. /// /// @param g Graph to inspect /// @throws IllegalArgumentException /// https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html public static void isConnected(Graph g) { // collect all vertices in the graph Collection<Vertex> c = g.vertices(); // pick a random vertice in the graph Vertex v = g.vertices().iterator().next(); // collect the set of visitable vertices Set<Vertex> visited = GraphAlgorithms.visitDepthFirst( g, v); // throw exception if not all vertices were visited if (visited.size() != c.size()) { throw new IllegalArgumentException( "graph is not connected"); } } }