diff --git a/src/atcoder/extra/graph/visualize.nim b/src/atcoder/extra/graph/visualize.nim deleted file mode 100644 index 28098ac0..00000000 --- a/src/atcoder/extra/graph/visualize.nim +++ /dev/null @@ -1,76 +0,0 @@ -when not declared ATCODER_GRAPH_VISUALIZE_HPP: - const ATCODER_GRAPH_VISUALIZE_HPP* = 1 - import atcoder/extra/graph/graph_template - import std/strformat, std/os - - proc is_weighted*(g:Graph):bool = - static: - assert g.adjType is ADJTYPE_SEQ - for u in 0 ..< g.len: - for e in g[u]: - if e.weight != 1: return true - return false - - proc is_directed*(g:Graph):bool = - static: - assert g.adjType is ADJTYPE_SEQ - for u in 0 ..< g.len: - for e in g[u]: - if e.rev == -1: return true - return false - - proc visualize*(g:Graph) = - var f: File = open("graph.html", FileMode.fmWrite) - var - nodes_array:seq[string] = @[] - edges_array:seq[string] = @[] - let is_directed = g.is_directed - let is_weighted = g.is_weighted - var found = initSet[(int, int)]() - for u in 0 ..< g.len: - nodes_array.add(fmt"{{id: {u}, label: '{u}'}}") - for i, e in g[u]: - if not is_directed: - if (u, i) in found: continue - found.incl((e.dst, e.rev)) - var s = fmt"from: {u}, to: {e.dst}" - if is_weighted: - s &= fmt", label: '{e.weight}'" - if is_directed: - s &= ", arrows: 'to'" - edges_array.add(fmt"{{ {s} }}") - let - nodes_info = nodes_array.join(",") - edges_info = edges_array.join(",") - var s = fmt""" - - - - - - - -
- - - -""" - f.write(s) - f.close - var r = execShellCmd("brave-browser graph.html") diff --git a/src/atcoder/extra/graph/visualizer.nim b/src/atcoder/extra/graph/visualizer.nim new file mode 100644 index 00000000..5759abff --- /dev/null +++ b/src/atcoder/extra/graph/visualizer.nim @@ -0,0 +1,86 @@ +when not declared ATCODER_GRAPH_VISUALIZER_HPP: + const ATCODER_GRAPH_VISUALIZER_HPP* = 1 + import atcoder/extra/graph/graph_template + import std/strformat, std/sets, std/strutils, std/browsers + proc visualize*(g:Graph, labels:seq[string] = @[], base = 0) = + var + node_data:seq[string] + edge_data:seq[string] + useNodeLabels = if labels.len == 0: false else: true + isEdgeWeighted = block: + var r = false + for u in 0 ..< g.len: + for e in g[u]: + if e.weight != 1: r = true + r + if useNodeLabels: + doAssert labels.len == g.len + for u in 0 ..< g.len: + var node_name = if useNodeLabels: labels[u] else: $(u + base) + node_data.add fmt"{{id: {$u}, label: '{node_name}'}}" + var undirected_edges = initHashSet[(int, int)]() + for u in 0 ..< g.len: + for e in g[u]: + let v = e.dst + var edge_label = if isEdgeWeighted: fmt"'{$e.weight}'" else: "undefined" + if e.rev == -1: + edge_data.add(fmt"{{from: {$u}, to: {$v}, arrows: 'to', label: {edge_label} }}") + else: + if (u, v) in undirected_edges: continue + edge_data.add(fmt"{{from: {$u}, to: {$v}, label: {edge_label} }}") + undirected_edges.incl((u, v)) + undirected_edges.incl((v, u)) + var html = """ + + + + + + + +
+ + + +""" + html = html.replace("<<>>", node_data.join(",")) + html = html.replace("<<>>", edge_data.join(",")) + var f = open("./graph.html", FileMode.fmWrite) + f.write(html) + openDefaultBrowser("./graph.html") + defer: close(f) diff --git a/src/atcoder/extra/other/floatutils.nim b/src/atcoder/extra/other/floatutils.nim index 63e6cfbd..2a044a00 100644 --- a/src/atcoder/extra/other/floatutils.nim +++ b/src/atcoder/extra/other/floatutils.nim @@ -61,16 +61,18 @@ when not declared ATCODER_FLOAT_UTILS_HPP: Real$.pi = pi() #echo machineEpsilon(Real) #Real$.eps = machineEpsilon(Real) * Real(10000) - block: - let one = Real(1) - var eps2 = one - while not (one + eps2 == one): - eps2 = eps2 / Real(2) - Real$.eps = eps2 * Real(5000) - when Real is float: - Real$.eps = 1e-12 + when Real is float | float64: + Real$.eps = 1e-9 + elif Real is float32: + Real$.eps = 1e-7 + else: + block: + let one = Real(1) + var eps2 = one + while not (one + eps2 == one): + eps2 = eps2 / Real(2) + Real$.eps = eps2 * Real(1000000) - # float comp # TODO: relative error proc `=~`*(a, b: Real): bool = abs(a - b) < Real$.eps proc `!=~`*(a, b: Real): bool = abs(a - b) > Real$.eps