Routing table optimization - algorithm

The problem i am trying to solve is, I have routing table
|src|dest|port|
| a | b | p1 |
| a | b | p2 |
| a | b | p3 |
| a | c | p1 |
| a | d | p2 |
| a | e | p3 |
This can be optimized to
|src|dest|port|
| a | b |p1,p2,p3|
| a | c | p1 |
| a | d | p2 |
| a | e | p3 |
Which can further be optimized to
|src|dest|port|
| a |b,c | p1 |
| a |b,d | p2 |
| a |b,e | p3 |
I thought of using 3 dimensional representation to solve this problem but again the retrieval will be complicated.
I need to use the best data structure to solve this use case.

The data structure is a set of sets of dest values, where the first set is keyed by src values and the second set is keyed by port values. This groups dest values by src and port:
src => port => [dest]
In python, this can be done with dictionaries:
table = (
('a','b','p1'),
('a','b','p2'),
('a','b','p3'),
('a','c','p1'),
('a','d','p2'),
('a','e','p3'),
)
optimized = {}
for route in table:
src, dest, port = route
o = optimized.get(src, {})
p = o.get(port, [])
p.append(dest)
o[port] = p
optimized[src] = o
for src,route in optimized.iteritems():
for port,dest in route.iteritems():
print src, dest, port
The result (in unsorted order) is:
a ['b', 'd'] p2
a ['b', 'e'] p3
a ['b', 'c'] p1
The lookup can be done using:
dest = optimized[src][port]

Related

Delete column and Add column with default value Amplify graphql DynamoDB Appsync

I want to delete the whole column at once if there 1000's of data deleting one by one is time consuming so is there any best way to do it
Deleting this column
And my next question is I need to add new column with default value aftering deleting
i.e :
id | x | y | z
| A | B | C
| A | B | C
| A | B | C
| A | B | C
If above is the the table with thousands of data , I want to delete "z" and add "newColumn" with default value of "D" as below
id | x | y | newColumn
| A | B | D
| A | B | D
| A | B | D
| A | B | D

Optimal algorithm to determine relationship tree

Suppose that you have a list of formulas like the following one:
KPI1 = somevalue1 + somevalue2
KPI2 = somevalue1 + somevalue3
KPI3 = KPI1 + somevalue4
KPI4 = KPI2 + KPI3
etc.
Which is the optimal algorithm that can be used to obtain a relationship tree for each of the elements referenced in the formulas?
i.e., using the example above:
+------------------------------------------------------------+
| somevalue3 somevalue1 somevalue2 somevalue4 |
| | | | | | |
| --------------- -------------- | |
| | | | |
| KPI2 KPI1 | |
| | | | |
| | --------------------- |
| | | |
| | KPI3 |
| | | |
| --------------------------- |
| | |
| KPI4 |
+------------------------------------------------------------+
You can use a hashmap where a key corresponds to a defined name (e.g. "KPI3"), and the corresponding value is a list of names/values on which that name depends (e.g. ["KPI1", somevalue4]).
Here is an implementation in JavaScript, where we can use the native Map constructor. Once the map is populated with all the dependencies, a recursive function can for example print the tree:
function printTree(map, name, indent="") {
console.log(indent + name);
let children = map.get(name);
if (children !== undefined) {
for (let childName of children) {
printTree(map, childName, indent+" ");
}
}
}
let map = new Map();
map.set("KPI1", ["value1", "value2"]);
map.set("KPI2", ["value1", "value3"]);
map.set("KPI3", ["KPI1", "value4"]);
map.set("KPI4", ["KPI2", "KPI3"]);
printTree(map, "KPI4");
In Python you would use a dictionary:
def print_tree(d, name, indent=""):
print(indent + name)
children = d.get(name, None)
if children is not None:
for childName in children:
print_tree(d, childName, indent+" ")
d = dict()
d["KPI1"] = ["value1", "value2"]
d["KPI2"] = ["value1", "value3"]
d["KPI3"] = ["KPI1", "value4"]
d["KPI4"] = ["KPI2", "KPI3"]
print_tree(d, "KPI4")

Ruby adding empty strings to hash for CSV spacing

I have:
hash = {"1"=>["A", "B", "C", ... "Z"], "2"=>["B", "C"], "3"=>["A", "C"]
My goal is to use hash as a source for creating a CSV with columns whose names are a letter of the alphabet and with rows hash(key) = 1,2,3 etc.
I created an array of all hash.values.unshift("")values that serve as row 1 (columns labels).
desired output:
| A | B | C | ... | Z |
1| A | B | C | ... | Z |
2| | B | C | ....... |
3| A | | C | ....... |
Creating CSV:
CSV.open("groups.csv", 'w') do |csv|
csv << row1
hash.each do |v|
csv << v.flatten
end
end
This makes the CSV look almost what I want but There is no spacing to get columns to align.
Any advice on how to make a method for modifying my hash that compares my all [A-Z] against each subsequent hash key (rows) to insert empty strings to provide spacing?
Can Class CSV do it better?
Something like this?
require 'csv'
ALPHA = ('A'..'Z').to_a.freeze
hash={"1"=>ALPHA, "2"=>["B", "C"], "3"=>["A", "C"]}
csv = CSV.generate("", col_sep: "|") do |csv|
csv << [" "] + ALPHA # header
hash.each do |k, v|
alphabet = ALPHA.map { |el| [el, 0] }.to_h
v.each { |el| alphabet[el] += 1 }
csv << [k, *alphabet.map { |k, val| val == 1 ? k : " " }]
end
end
csv.split("\n").each { |row| puts row }
output:
|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
1|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
2| |B|C| | | | | | | | | | | | | | | | | | | | | | |
3|A| |C| | | | | | | | | | | | | | | | | | | | | | |
If your values are truly single characters and don't need the CSV escaping, then I recommend bypassing CSV altogether and building the string in plain Ruby.
Assuming you want to align your lines correctly regardless of the number of digits in the row number (e.g. 1, 10, and 100), you can use printf style formatting to guarantee horizontal aligment (assuming your row number width never exceeds the value of ROWNUM_WIDTH).
By the way, I changed the hash's keys to integers, hope that's ok.
#!/usr/bin/env ruby
FIELDS = ('A'..'Z').to_a
DATA = { 1 => FIELDS, 2 => %w(B C), 3 => %w(A C) }
ROWNUM_WIDTH = 3
output = ' ' * ROWNUM_WIDTH + " | #{FIELDS.join(' | ')} |\n"
DATA.each do |rownum, values|
line = "%*d | " % [ROWNUM_WIDTH, rownum]
FIELDS.each do |field|
char = values.include?(field) ? field : ' '
line << "#{char} | "
end
output << line << "\n"
end
puts output
=begin
Outputs:
| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
1 | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
2 | | B | C | | | | | | | | | | | | | | | | | | | | | | | |
3 | A | | C | | | | | | | | | | | | | | | | | | | | | | | |
=end
all = [*?A..?Z]
hash = {"1"=>[*?A..?Z], "2"=>["B", "C"], "3"=>["A", "C"]}
hash.map do |k, v|
[k, *all.map { |k| v.include?(k) ? k : ' ' }]
end.unshift([' ', *all]).
map { |row| row.join('|') }
#⇒ [
# [0] " |A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
# [1] "1|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z",
# [2] "2| |B|C| | | | | | | | | | | | | | | | | | | | | | | ",
# [3] "3|A| |C| | | | | | | | | | | | | | | | | | | | | | | "
# ]

RST/Sphinx create inline target markup inside array

I have an array in sphinx / rst, and I would like to reference a line or cell from other part of my documentation.
How can I create an inline markup reference target in the array?
The array looks like this:
+-----------------+-------------------------+-------------------------------------------------------+
| e | c | p |
+=================+=========================+=======================================================+
| e1 | c1 | p1 |
+-----------------+-------------------------+-------------------------------------------------------+
| e2 | c2 | p2 |
+-----------------+-------------------------+-------------------------------------------------------+
I did not think this was possible, but this worked for me.
+----+----+-------------------------+
| e | c | .. _my-reference-label: |
| | | |
| | | p |
+====+====+=========================+
| e1 | c1 | p1 |
+----+----+-------------------------+
| e2 | c2 | p2 |
+----+----+-------------------------+
and then the link to the target would be:
:ref:`Link title <my-reference-label>`.
The formatting makes the targeted cell larger than it should be, but you can fiddle with the other column widths to get percentage widths close enough.

Ruby: trouble with batch variable assignment

Yesterday, I started making a chess program and, trying to save 60-odd lines, decided to try my hand at batch variable assignment. That is, assigning variables through loops. I can't seem to join spot_def_letters[i] with o_s in the correct fashion, though. ($board is scoped for later use)
My code:
spot_def_letters = ["a", "b", "c", "d", "e", "f", "g", "h"]
8.times do
i = 0
o = 1
8.times do
o_s = o.to_s
spot_def_letters[i] + o_s = " "
o += 1
end
end
$board = """
| | | | | | |
#{a8}|#{b8}|#{c8}|#{d8}|#{e8}|#{f8}|#{g8}|#{h8}
| | | | | | |
#{a7}|#{b7}|#{c7}|#{d7}|#{e7}|#{f7}|#{g7}|#{h7}
| | | | | | |
#{a6}|#{b6}|#{c6}|#{d6}|#{e6}|#{f6}|#{g6}|#{h6}
| | | | | | |
#{a5}|#{b5}|#{c5}|#{d5}|#{e5}|#{f5}|#{g5}|#{h5}
| | | | | | |
#{a4}|#{b4}|#{c4}|#{d4}|#{e4}|#{f4}|#{g4}|#{h4}
| | | | | | |
#{a3}|#{b3}|#{c3}|#{d3}|#{e3}|#{f3}|#{g3}|#{h3}
| | | | | | |
#{a2}|#{b2}|#{c2}|#{d2}|#{e2}|#{f2}|#{g2}|#{h2}
| | | | | | |
#{a1}|#{b1}|#{c1}|#{d1}|#{e1}|#{f1}|#{g1}|#{h1}
"""
instead of indexing into string arrays and using a bunch of sneaky, bad-looking code, I decided to use a 64-value array (spots = Array.new(64, " ")) and puts those values.

Resources