Tree Level-Order Traversal of Elements in a Vector - algorithm

I am looking for an algorithm to take a list of x values and loop through them starting in the middle then the middle of the left then the middle of the right, then the middle of the middle of the left...like a tree.
I don't think recursion will work because it will traverse down one side completely before getting to the other side. I need to parse through evenly.
Pretend this is a list of 50 numbers:
.................................................. (50)
Need to find the 25th element first
........................1......................... (lvl1)
Then the 12th, then 38th
...........2.........................3............ (lvl2)
Then the 6,18 31,44
.....4...........5.............6...........7...... (lvl3)
Then the 3,9,15,21 28,34,41,48
..8.....9.....a......b.....c.......d.....e.....f.. (lvl4)
etc... until all the values have been traversed. So by the time lvl4 is hit, i've seen 1,2,3,4,5,6,7,8,9,a,b,c,d,e,f in that order.
All my attempts have flopped to do this iteratively.
Efficiency is not critical as it won't be run often.
Hopefully my question is clear. Thank-you

You can solve this via a queue data structure and some math.
Start by pushing in the tuple (0, 25, 49). This indicates that this is a node at position 25, splitting the range 0-49. So the queue should look like this:
[(0, 25, 49)]
Now at each point, remove the front of the queue, print the element at the index, and push in the descendants. So, for example, when you pop (0, 25, 49), how to track the descendants? The left descendant is the middle of the range 0-24, so you would push in (0, 12, 24). The right descendant is the middle of the range 26-49, so you would push in (26, 38, 49). So the queue should look like this:
[(0, 13, 23), (26, 38, 49)].
Et cetera.

(The solution that follows is written in Swift, but I hope you can follow it and translate to your favourite language of choice, in case you wish to make use of it)
We can quite easily come up with a solution that works in the special case where your number of array values describe a full(/proper) binary tree, i.e., if numElements = 2^(lvl-1)+1, where lvl is the level of your tree. See function printFullBinaryTree(...) below.
Now, we can also somewhat with ease expand any array into one that describes a full binary tree, see expandToFullBinary. '
By combining these two methods, we have a general method for input arrays of any size.
Expand any array into one that describes a full binary tree:
/* given 'arr', returns array expanded to full binary tree (if necessary) */
func expandToFullBinary(arr: [String], expandByCharacter: String = "*") -> [String] {
let binLength = Int(pow(2.0,Double(Int(log2(Double(arr.count)))+1)))-1
if arr.count == binLength {
return arr
}
else {
let diffLength = binLength - arr.count
var arrExpanded = [String](count: binLength, repeatedValue: expandByCharacter)
var j = 0
for i in 0 ..< arr.count {
if i < (arr.count - diffLength) {
arrExpanded[i] = arr[i]
}
else {
arrExpanded[i+j] = arr[i]
j = j+1
}
}
return arrExpanded
}
}
Print array (that describes a full binary tree) as a binary tree according to your question specifications:
/* assumes 'arr' describes a full binary tree */
func printFullBinaryTree(arr: [String]) {
var posVectorA : [Int] = [arr.count/2]
var posVectorB : [Int]
var splitSize : Int = arr.count/2
var elemCount = 0
if arr.count < 2 {
print("\(arr.first ?? "")")
}
else {
while elemCount < arr.count {
posVectorB = []
splitSize = splitSize/2
for i in posVectorA {
if elemCount == arr.count {
print("noo")
break
}
print(arr[i], terminator: " ")
elemCount = elemCount + 1
posVectorB.append(i-splitSize-1)
posVectorB.append(i+splitSize+1)
}
print("")
posVectorA = posVectorB
}
}
}
Example for a vector describing a full binary tree as well as one describing a non-full binary tree:
/* Example */
var arrFullBinary : [String] = ["8", "4", "9", "2", "a", "5", "b", "1", "c", "6", "d", "3", "e", "7", "f"]
var arrNonFullBinary : [String] = ["g", "8", "h", "4", "i", "9", "j", "2", "a", "5", "b", "1", "c", "6", "d", "3", "e", "7", "f"]
printFullBinaryTree(expandToFullBinary(arrFullBinary, expandByCharacter: ""))
/* 1
2 3
4 5 6 7
8 9 a b c d e f */
printFullBinaryTree(expandToFullBinary(arrNonFullBinary, expandByCharacter: ""))
/* 1
2 3
4 5 6 7
8 9 a b c d e f
g h i j */

Related

How to sort a Vec by indices?

I want to sort (reorder) a Vec in-place by a predefined ordering in Rust.
For example:
let i = vec![0, 3, 2, 1];
let mut v = vec!["a", "b", "c", "d"];
v.sort_by_indices(&i);
assert_eq!(v, &["a", "d", "c", "b"]);
I would like to do this in-place. In my use case, v takes up a lot of memory.
This question is a follow-up to How to get the indices that would sort a Vec?
An in-place implementation is tricky but possible in O(n) time. It works by chasing indices and swapping elements until it gets back to where it started. Unfortunately, this does require scratch space to keep track of what elements are already sorted. Here's an implementation that reuses the index array if its allowed to consume it:
fn sort_by_indices<T>(data: &mut [T], mut indices: Vec<usize>) {
for idx in 0..data.len() {
if indices[idx] != idx {
let mut current_idx = idx;
loop {
let target_idx = indices[current_idx];
indices[current_idx] = current_idx;
if indices[target_idx] == target_idx {
break;
}
data.swap(current_idx, target_idx);
current_idx = target_idx;
}
}
}
}
See it working on the playground (with improvements by #Jmb).
Otherwise you would need a separate allocation for the scratch space (perhaps a BitVec). Feel free to comment or edit if this method is possible without keeping track of the sorted elements.
In the same way it enough to implement yourself
let i = vec![0, 3, 2, 1];
let mut v = vec!["a", "b", "c", "d"];
v = i.into_iter().map(|x| v[x]).collect::<Vec<&str>>();
assert_eq!(v, &["a", "d", "c", "b"]);
You can create a HashMap or BTreeMap lookup table and use it as key searcher:
use std::collections::HashMap;
fn main() {
let i = vec![0, 3, 2, 1];
let mut v = vec!["a", "b", "c", "d"];
let keys: HashMap<_, _> = v.iter().cloned().zip(i.iter()).collect();
v.sort_by_cached_key(|e| keys[e]);
assert_eq!(v, &["a", "d", "c", "b"]);
}
Playground

Sum-String coding algorithm

I am trying to solve the first question from http://www.geeksforgeeks.org/nutanix-interview-experience-set-1-on-campus-for-internship/. In this question, we're given a string of decimal digits, and we have to figure out if there's some way to split it up into four or more substrings ["A", "B", "C", …] such that A + B = C, B + C = D, etc.
For example, if the string is "12358", then the answer is true, because we can split it up into ["1", "2", "3", "5", "8"], where 1 + 2 = 3, 2 + 3 = 5, and 3 + 5 = 8.
Similarly, if the string is "199100199", then the answer is true, because we can split it up into ["1", "99", "100", "199"], where 1 + 99 = 100 and 99 + 100 = 199.
However, if the string is "2368", then the answer is false, because there's only way to break it up into four or more substrings — namely ["2", "3", "6", "8"] — and 3 + 6 ≠ 8.
I can probably think of a solution using two or three nested loops, but I assume I need a more efficient solution?
public static boolean test3(String s, String d1, String d2, int idx1, int idx2) {
if(idx1>=s.length()) return false;
if(idx2>=s.length()) {
d1 = s.substring(0,idx1);
return test3(s,d1,d2,idx1+1,1);
}
if(!d1.isEmpty() && d1.length()+idx2<=s.length()) {
d2 = s.substring(d1.length(),d1.length()+idx2);
int sum = Integer.parseInt(d1) + Integer.parseInt(d2);
String sumStr = Integer.toString(sum);
if(s.substring(d1.length()+d2.length()).startsWith(sumStr)) {
return true;
} else {
return test3(s,d1,d2,idx1,idx2+1);
}
} else {
d1 = s.substring(0,idx1);
return test3(s,d1,d2,idx1+1,idx2);
}
}
I tried the above and it seems to work. This is my solution

Lua - Sort table and randomize ties

I have a table with two values, one is a name (string and unique) and the other is a number value (in this case hearts). What I want is this: sort the table by hearts but scramble randomly the items when there is a tie (e.g. hearts is equal). By a standard sorting function, in case of ties the order is always the same and I need it to be different every time the sorting function works.
This is anexample:
tbl = {{name = "a", hearts = 5}, {name = "b", hearts = 2}, {name = "c", hearts = 6}, {name = "d", hearts = 2}, {name = "e", hearts = 2}, {name = "f", hearts = 7}}
sort1 = function (a, b) return a.hearts > b.hearts end
sort2 = function (a, b)
if a.hearts ~= b.hearts then return a.hearts > b.hearts
else return a.name > b.name end
end
table.sort(tbl, sort2)
local s = ""
for i = 1, #tbl do
s = s .. tbl[i].name .. "(" .. tbl[i].hearts .. ") "
end
print(s)
Now, with the function sort2 I think I quite got the problem. The problem is, what happens when a.hearts == b.hearts? In my code it just orders the ties by their name, not what I want. I have two ideas:
First scramble randomly all the items in the table, then apply sort1.
Add a value to every element of the table, called rnd, that is a random number. Then in sort2, when a.hearts == b.hearts order the items by a.rnd > b.rnd.
In sort2, when a.hearts == b.hearts generate randomly true or false and return it. It doesn't work, and I understand that this happens because the random true/false makes the order function crash since there could be inconsistencies.
I don't like 1 (because I would like to do everything inside the sorting function) and 2 (since it requires to add a value), I would like to do something like 3 but working. The question is: is there a way do to this in a simple manner, and what is an optimal way of doing this? (maybe, method 1 or 2 are optimal and I don't get it).
Bonus question. Moreover, I need to fix an item and sort the others. For example, suppose we want "c" to be first. Is it good to make a separate table with only the items to sort, sort the table and then add the fixed items?
-- example table
local tbl = {
{ name = "a", hearts = 5 },
{ name = "b", hearts = 2 },
{ name = "c", hearts = 6 },
{ name = "d", hearts = 2 },
{ name = "e", hearts = 2 },
{ name = "f", hearts = 7 },
}
-- avoid same results on subsequent requests
math.randomseed( os.time() )
---
-- Randomly sort a table
--
-- #param tbl Table to be sorted
-- #param corrections Table with your corrections
--
function rnd_sort( tbl, corrections )
local rnd = corrections or {}
table.sort( tbl,
function ( a, b)
rnd[a.name] = rnd[a.name] or math.random()
rnd[b.name] = rnd[b.name] or math.random()
return a.hearts + rnd[a.name] > b.hearts + rnd[b.name]
end )
end
---
-- Show the values of our table for debug purposes
--
function show( tbl )
local s = ""
for i = 1, #tbl do
s = s .. tbl[i].name .. "(" .. tbl[i].hearts .. ") "
end
print(s)
end
for i = 1, 10 do
rnd_sort(tbl)
show(tbl)
end
rnd_sort( tbl, {c=1000000} ) -- now "c" will be the first
show(tbl)
Here's a quick function for shuffling (scrambling) numerically indexed tables:
function shuffle(tbl) -- suffles numeric indices
local len, random = #tbl, math.random ;
for i = len, 2, -1 do
local j = random( 1, i );
tbl[i], tbl[j] = tbl[j], tbl[i];
end
return tbl;
end
If you are free to introduce a new dependency, you can use lazylualinq to do the job for you (or check out how it sorts sequences, if you do not need the rest):
local from = require("linq")
math.randomseed(os.time())
tbl = {{name = "a", hearts = 5}, {name = "b", hearts = 2}, {name = "c", hearts = 6}, {name = "d", hearts = 2}, {name = "e", hearts = 2}, {name = "f", hearts = 7}}
from(tbl)
:orderBy("x => x.hearts")
:thenBy("x => math.random(-1, 1)")
:foreach(function(_, x) print(x.name, x.hearts) end)

Palindrome count in a string

So, I explored www.hackerearth.com today and was solving my first problem statement in ruby: http://www.hackerearth.com/problem/algorithm/palindrome-count-1/
Palindrome count Problem:
Given a string S, count the number of non empty sub strings that are palindromes.
A sub string is any continuous sequence of characters in the string.
A string is said to be palindrome, if the reverse of the string is same as itself.
Two sub strings are different if they occur at different positions in S
Input: Input contains only a single line that contains string S.
Output: Print a single number, the number of sub strings that are palindromes.
Constraints
1 <= |S| <= 50
S contains only lower case latin letters, that is characters a to z.
Sample Input (Plaintext Link): dskjkd
Sample Output (Plaintext Link): 7
Explanation -
The 7 sub strings are d, s, k, j, k, d, kjk.
Time limit 3 sec(s)
Memory limit 256 MB
Source limit 1024 KB
Here is what I did:
chars = gets.chomp.gsub(' ', '').split('')
counts = chars.count
(2..chars.count).each do |len|
chars.combination(len).each do |comb|
string = comb.inject(:<<)
counts += 1 if string.reverse == string
end
end
puts counts
However, this approach seems to be inefficient in terms of the time execution and memory usage. Is there any way to optimize this? Or have any other approach to this solution, algorithm is also welcome as solution! Thanks.
Edit
Since, all the answers are correct. I had to choose the one which is efficient. So, I ran benchmark and here is the result: https://gist.github.com/suryart/7577481
Based on the result you can see this answer is much faster. Thank you for the new approaches/ solution guys! :)
This approach -- in pseudo-code -- should work.
input: String s
// each single letter is palindrome itself
palindromsCount = length(s)
// let count all odd-length palindromes first (palindrome of length 1 already counted)
// we will be checking from the very middle of a sub-string, if it is symmetric
for(int i = 1; i < length(s)-1; i++)
for(int j = 1; ; j++)
if (i - j < 0 || i + j >= length(s) || s[i-j] != s[i+j])
break
else
palindromsCount += 1
// let count in similar way all even-length palindromes
for(int i = 0; i < length(s)-1; i++)
for(int j = 0; ; j++)
if (i - j < 0 || i + j + 1 >= length(s) || s[i-j] != s[i+j+1])
break
else
palindromsCount += 1
EDIT Of course both loops can be combined into a single one -- I did not want to do it for better readability.
using the algorithm to get all subsets of the string from What is the best way to split a string to get all the substrings by Ruby?
count = 0
(0..len-1).each do |i|
(i..len-1).each do |j|
temp = s[i..j]
count = count + 1 if temp == temp.reverse
end
end
puts "found #{count} palindromes"
Enumerable#each_cons is handy here:
str = "momanddadpaddledthekayak"
b = str.chars
(1..b.size).reduce(0) {|t,n| t + b.each_cons(n).reduce(0) \
{|r,e| w = e.join; w==w.reverse ? r + 1 : r}} # => 30
If we want to see the palendromes:
b = str.chars
pals = (1..b.size).each_with_object([]) {|n, a| b.each_cons(n).each \
{|e| w = e.join; a << w if w==w.reverse}}
p pals.size # => 30
p pals # => ["m", "o", "m", "a", "n", "d", "d", "a", "d", "p", "a",\
"d", "d", "l", "e", "d", "t", "h", "e", "k", "a", "y",
"a", "k", "dd", "dd", "mom", "dad", "aya", "kayak"]
Edit: #squiguy made the useful observation that we may not want to count duplicates. If that's the case, my first calculation above could not be used and the second would have to be changed as squiguy suggests (e.g., p a.uniq.size) or changed to build a hash rather than an array:
b = str.chars
pals = (1..b.size).each_with_object({}) {|n,h| b.each_cons(n).each \
{|e| w = e.join; h[w] = 0 if w==w.reverse}}.keys
p pals.size # => 17
p pals# => ["m", "o", "a", "n", "d", "p", "l", "e", "t",\
"h", "k", "y", "dd", "mom", "dad", "aya", "kayak"]
[Edit: replaced each with each_with_object. On rereading the question, it appears that dups are to be counted.]

Fastest way to get values from 2d array

I have 2d aray similar to this:
string[,] arr = {
{ "A", "A", "A", "A", "A", "A", "A", "D", "D", "D", "D", "D", "D", "D", "D" },
{ "1", "1", "1", "1", "1", "1", "1", "0", "0", "0", "0", "0", "0", "0", "0" },
{ "2", "2", "2", "2", "2", "2", "2", "00", "00", "00", "00", "00", "00", "00", "00" }
};
I am trying to get following result from above array:
A 1 2
A 1 2
A 1 2
A 1 2
A 1 2
A 1 2
Get all "A" from the array at length 0. Than get corrospoding values of it from other columns.
This is big 2d array with over 6k values. But design is exactly same as described above. I have tried 2 ways so far:
1st method: using for loop to go through all the values:
var myList = new List<string>();
var arrLength = arr.GetLength(1)-1;
for (var i = 0; i < arrLength; i++)
{
if (arr[0,i].Equals("A"))
myList.Add(arr[0, i]);
else
continue;
}
}
2nd method: creating list and than going through all values:
var dataList = new List<string>();
var list = Enumerable.Range(0, arr.GetLength(1))
.Select(i => arr[0, i])
.ToList();
var index = Enumerable.Range(0, arr.GetLength(1))
.Where(index => arr[0, index].Contains("A"))
.ToArray();
var sI = index[0];
var eI = index[index.Length - 1];
myList.AddRange(list.GetRange(sI, eI - sI));
They both seem to be slow, not efficient enough. Is there any better way of doing this?
I like to approach these kinds of algorithms in a way that my code ends up being self-documenting. Usually, describing the algorithm with your code, and not bloating it with code features, tends to produce pretty good results.
var matchingValues =
from index in Enumerable.Range(0, arr.GetLength(1))
where arr[0, index] == "A"
select Tuple.Create(arr[1, index], arr[2, index]);
Which corresponds to:
// find the tuples produced by
// mapping along one length of an array with an index
// filtering those items whose 0th item on the indexed dimension is A"
// reducing index into the non-0th elements on the indexed dimension
This should parallelize extremely well, as long as you keep to the simple "map, filter, reduce" paradigm and refrain from introducing side-effects.
Edit:
In order to return an arbitrary collection of the columns associated with an "A", you can:
var targetValues = new int[] { 1, 2, 4, 10 };
var matchingValues =
from index in Enumerable.Range(0, arr.GetLength(1))
where arr[0, index] == "A"
select targetValues.Select(x => arr[x, index]).ToArray();
To make it a complete collection, simply use:
var targetValues = Enumerable.Range(1, arr.GetLength(0) - 1).ToArray();
As "usr" said: back to the basics if you want raw performance. Also taking into account that the "A" values can start at an index > 0:
var startRow = -1; // "row" in the new array.
var endRow = -1;
var match = "D";
for (int i = 0; i < arr.GetLength(1); i++)
{
if (startRow == -1 && arr[0,i] == match) startRow = i;
if (startRow > -1 && arr[0,i] == match) endRow = i + 1;
}
var columns = arr.GetLength(0);
var transp = new String[endRow - startRow,columns]; // transposed array
for (int i = startRow; i < endRow; i++)
{
for (int j = 0; j < columns; j++)
{
transp[i - startRow,j] = arr[j,i];
}
}
Initializing the new array first (and then setting the "cell values) is the main performance boost.

Resources