package hjelpeklasser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringJoiner;
import java.util.TreeMap;
public final class VGraf implements Iterable<String>
{
private static final class Node
{
private static final int uendelig = 0x7fffffff;
private final String navn;
private final List<Kant> kanter;
private int avstand = uendelig;
private boolean ferdig = false;
private Node forrige = null;
private Node(String navn)
{
this.navn = navn;
kanter = new LinkedList<>();
}
@Override
public String toString() { return navn; }
}
private static final class Kant
{
private final Node til;
private int vekt;
private Kant(Node til, int vekt)
{
this.til = til;
this.vekt = vekt;
}
@Override
public String toString() { return "(" + til.navn + "," + vekt + ")"; }
}
private final Map<String, Node> noder;
public VGraf()
{
noder = new TreeMap<>();
}
public boolean leggInnNode(String navn)
{
if (navn == null) throw new IllegalArgumentException("navn er null!");
if (noder.get(navn) != null) return false;
noder.put(navn, new Node(navn));
return true;
}
public int leggInnKant(String franode, String tilnode, int vekt)
{
if (franode.equals(tilnode)) throw
new IllegalArgumentException(franode + " er lik " + tilnode + "!");
Node fra = noder.get(franode);
if (fra == null) throw new NoSuchElementException(franode + " er ukjent!");
Node til = noder.get(tilnode);
if (til == null) throw new NoSuchElementException(tilnode + " er ukjent!");
for (Kant kant : fra.kanter)
{
if (kant.til == til)
{
int gammelvekt = kant.vekt;
kant.vekt = vekt;
return gammelvekt;
}
}
fra.kanter.add(new Kant(til, vekt));
return vekt;
}
public boolean erKant(String franode, String tilnode)
{
Node fra = noder.get(franode);
if (fra == null) throw new NoSuchElementException(franode + " er ukjent!");
Node til = noder.get(tilnode);
if (til == null) throw new NoSuchElementException(tilnode + " er ukjent!");
for (Kant k : fra.kanter) if (k.til == til) return true;
return false;
}
public boolean fjernKant(String franode, String tilnode)
{
Node fra = noder.get(franode);
if (fra == null) throw new NoSuchElementException(franode + " er ukjent!");
Node til = noder.get(tilnode);
if (til == null) throw new NoSuchElementException(tilnode + " er ukjent!");
for (Iterator<Kant> i = fra.kanter.iterator(); i.hasNext(); )
{
Kant k = i.next();
if (k.til == til)
{
i.remove();
return true;
}
}
return false;
}
public String[] kantTabellFra(String node)
{
Node fra = noder.get(node);
if (fra == null) throw new NoSuchElementException(node + " er ukjent!");
String[] tabell = new String[fra.kanter.size()];
int i = 0;
for (Kant k : fra.kanter) tabell[i++] = k.til.navn;
return tabell;
}
public String[] kantTabellTil(String node)
{
Node til = noder.get(node);
if (til == null) throw new NoSuchElementException(node + " er ukjent!");
List<String> liste = new ArrayList<>();
for (String franode : noder.keySet())
{
for (Kant k : noder.get(franode).kanter)
{
if (k.til == til) liste.add(franode);
}
}
return liste.toArray(new String[liste.size()]);
}
public boolean fjernNode(String node)
{
if (kantTabellFra(node).length == 0 && kantTabellTil(node).length == 0)
{
noder.remove(node);
return true;
}
return false;
}
public VGraf(String url) throws IOException
{
this();
BufferedReader inn = new BufferedReader
(new InputStreamReader((new URL(url)).openStream()));
String linje;
while ((linje = inn.readLine()) != null)
{
String[] s = linje.split(" ");
String fra = s[0];
leggInnNode(fra);
for (int i = 1; i < s.length; i += 2)
{
String til = s[i];
int vekt = Integer.parseInt(s[i + 1]);
leggInnNode(til);
leggInnKant(fra, til, vekt);
}
}
}
public String kanterFra(String node)
{
Node fra = noder.get(node);
if (fra == null) return node + " er ukjent!";
StringJoiner sj = new StringJoiner(", ");
for (Kant k : fra.kanter) sj.add(k.toString());
return sj.toString();
}
@Override
public Iterator<String> iterator()
{
return noder.keySet().iterator();
}
public void kortestVeiFra(String nodenavn)
{
Node start = noder.get(nodenavn);
if (start == null) throw new NoSuchElementException(nodenavn + " er ukjent!");
start.avstand = 0;
while (true)
{
int minstavstand = Node.uendelig;
Node minst = null;
for (Node n : noder.values()) if (!n.ferdig && n.avstand < minstavstand)
{
minstavstand = n.avstand; minst = n;
}
if (minstavstand == Node.uendelig) break;
for (Kant k : minst.kanter)
{
if (minst.avstand + k.vekt < k.til.avstand)
{
k.til.avstand = minst.avstand + k.vekt;
k.til.forrige = minst;
}
}
minst.ferdig = true;
}
}
public int avstand(String nodenavn)
{
Node node = noder.get(nodenavn);
if (node == null) throw new NoSuchElementException(node + " er ukjent!");
return node.avstand;
}
public String veiTil(String nodenavn)
{
Node node = noder.get(nodenavn);
if (node == null) throw new NoSuchElementException(node + " er ukjent!");
Deque<String> kø = new LinkedList<>();
while (node != null)
{
kø.addFirst(node.navn);
node = node.forrige;
}
return kø.toString();
}
public void nullstill()
{
for (Node node : noder.values())
{
node.avstand = Node.uendelig;
node.ferdig = false;
node.forrige = null;
}
}
}