This is my first post here but reading other posts has helped me with countless issues. You guys are awesome. So thanks for all the help you guys have provided up to this point and thanks in advance for any advice you can give me here.
So, I'm working on this script that will end up randomly choosing numbers from a list in an array. What I'm trying to do in this section is read the number in each element of the third dimension of NumberHistoryArray and write the corresponding number from the second dimension the number of times indicated in the third into the numberDump array. I also have it writing to a text file just to see that it works and to have something to reference if I run into other problems and need to know what the output is.
Edit
The second dimension of NumberHistoryArray contains the numbers 1 through 35. The third dimension contains the number of times each of the numbers in the second dimension should be repeated when written to the numberDump array.
If NumberHistoryArray(4, 0, 0) is 4, for example, it should write the number 1 four times, once each in numberDump(0, 0, 0) through (0, 0, 3) and dynamically resize numberDump() as needed to fit each 1. The result of echoing numberDump(0, 0, 0) through numberDump(0, 0, 3) should be 1 1 1 1. If NumberHistoryArray(4, 1, 1) is 7, it should write the number 2 seven times in numberDump(1, 1, 0).
Edit
When writing to the numberDump text file from within the Do loop, the text file is perfect. If I echo the contents of each element in the array from inside the Do loop, the contents are accurate. Once outside the Do loop, the contents are blank. Any takers?
Dim NumberHistoryArray(5, 34, 3)
Dim numberDump()
reDim numberDump(3, 34, 0)
' generate the number list and store it in the array
For n = LBound(numberDump, 1) to UBound(numberDump, 1)
i = 1
x = 0
y = 1
Do
Set objTextFile = objFSO.OpenTextFile("numberDump.txt", 8, True)
' determine how many elements are needed in the third dimension of the
' array to store the output
x = x + NumberHistoryArray(4, i - 1, n)
' resize the array
ReDim Preserve numberDump(3, 34, x)
' input the numbers
For z = y to UBound(NumberDump, 3)
numberDump(n, i - 1, z) = i
objTextFile.WriteLine(numberDump(n, i - 1, z))
Next
objTextFile.Close
y = x + 1
i = i + 1
Loop Until i = 36
Next
For i = 0 to UBound(numberDump, 2)
For j = 0 to UBound(numberDump, 3)
wscript.Echo numberDump(0, i, j)
Next
Next
The issue here is that you are resizing the third dimension of numberDump to x each iteration, and you are resetting the value of x with each iteration of n. For example, when n is 0, by the end of the Do loop, x may be equal to 10. However, on the next iteration, when n is 1, x is reset to 0 and you end up resizing the third dimension of numberDump to 0, erasing most of the existing elements.
There are two methods of working around this:
Keep track of the maximum value of x for all iterations of n. Use that value to resize numberDump as necessary.
Use a jagged array (aka, an array of arrays). In this case, numberDump would be a two-dimensional array whose values are arrays containing the repeated values. This would allow each value to have a different length, as opposed to a three-dimensional array, where the third dimension always has the same length.
Ever heard of life span of objects? Where do you initialize the objects : within a loop or outside the loop so that it can be referred within the entire sub routine/function.
How do you refer to Array elements outside the loop? Each element has an index. So you elment is referred via the index.
e.g. ArrayOne has 3 elements from Lower bound 0 to 2. Within your loops you can refer to ArrayOne(1) to get 2nd element.
Other than using indices to refer elements, you can also try to view array elements during the debug mode on immediate window or watch window.
So as you check on these tips, please show us a proper complete code for further verification.
Related
I'm going through the Daily Coding Problems and am currently stuck in one of the problems. It goes by:
You are given an array of length N, where each element i represents
the number of ways we can produce i units of change. For example, [1,
0, 1, 1, 2] would indicate that there is only one way to make 0, 2, or
3 units, and two ways of making 4 units.
Given such an array, determine the denominations that must be in use.
In the case above, for example, there must be coins with values 2, 3,
and 4.
I'm unable to figure out how to determine the denomination from the total number of ways array. Can you work it out?
Somebody already worked out this problem here, but it's devoid of any explanation.
From what I could gather is that he collects all the elements whose value(number of ways == 1) and appends it to his answer, but I think it doesn't consider the fact that the same number can be formed from a combination of lower denominations for which still the number of ways would come out to be 1 irrespective of the denomination's presence.
For example, in the case of arr = [1, 1, a, b, c, 1]. We know that denomination 1 exists since arr[1] = 1. Now we can also see that arr[5] = 1, this should not necessarily mean that denomination 5 is available since 5 can be formed using coins of denomination 1, i.e. (1 + 1 + 1 + 1 + 1).
Thanks in advance!
If you're solving the coin change problem, the best technique is to maintain an array of ways of making change with a partial set of the available denominations, and add in a new denomination d by updating the array like this:
for i = d upto N
a[i] += a[i-d]
Your actual problem is the reverse of this: finding denominations based on the total number of ways. Note that if you know one d, you can remove it from the ways array by reversing the above procedure:
for i = N downto d
a[i] -= a[i-d]
You can find the lowest denomination available by looking for the first 1 in the array (other than the value at index 0, which is always 1). Then, once you've found the lowest denomination, you can remove its effect on the ways array, and repeat until the array is zeroed (except for the first value).
Here's a full solution in Python:
def rways(A):
dens = []
for i in range(1, len(A)):
if not A[i]: continue
dens.append(i)
for j in range(len(A)-1, i-1, -1):
A[j] -= A[j-i]
return dens
print(rways([1, 0, 1, 1, 2]))
You might want to add error-checking: if you find a non-zero value that's not 1 when searching for the next denomination, then the original array isn't valid.
For reference and comparison, here's some code for computing the ways of making change from a set of denominations:
def ways(dens, N):
A = [1] + [0] * N
for d in dens:
for i in range(d, N+1):
A[i] += A[i-d]
return A
print(ways([2, 3, 4], 4))
I've a piece of code to randomize the order of words in a text file, but I'm not sure exactly what it's doing. Here is the code.
Randomize()
For count = 1 To 10
rand = (Int((10 - count + 1) * Rnd() + count))
temp = words(count)
words(count) = words(rand)
words(rand) = temp
Next
Could somebody please explain this to me? Thanks in advance.
first check msdn rnd description and note:
The Rnd function returns a value less than 1 but greater than or equal to 0
and
To produce random integers in a given range, use this formula: Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
having this in mind, we see next algorithm:
set current word index to 1 (first word)
pick random index which is equals or greater then current (ie select word from the rest of array)
swap current word with randomly picked
increase current word index (ie reduce size of unassigned words pool)
go to #2
you can also use a little bit different description:
imagine that you have un-ordered set of words, you pick random one, remove it from set and append it to ordered array, so finally you will have randomly ordered array of words from original set
Source : Google Interview Question
Write a routine to ensure that identical elements in the input are maximally spread in the output?
Basically, we need to place the same elements,in such a way , that the TOTAL spreading is as maximal as possible.
Example:
Input: {1,1,2,3,2,3}
Possible Output: {1,2,3,1,2,3}
Total dispersion = Difference between position of 1's + 2's + 3's = 4-1 + 5-2 + 6-3 = 9 .
I am NOT AT ALL sure, if there's an optimal polynomial time algorithm available for this.Also,no other detail is provided for the question other than this .
What i thought is,calculate the frequency of each element in the input,then arrange them in the output,each distinct element at a time,until all the frequencies are exhausted.
I am not sure of my approach .
Any approaches/ideas people .
I believe this simple algorithm would work:
count the number of occurrences of each distinct element.
make a new list
add one instance of all elements that occur more than once to the list (order within each group does not matter)
add one instance of all unique elements to the list
add one instance of all elements that occur more than once to the list
add one instance of all elements that occur more than twice to the list
add one instance of all elements that occur more than trice to the list
...
Now, this will intuitively not give a good spread:
for {1, 1, 1, 1, 2, 3, 4} ==> {1, 2, 3, 4, 1, 1, 1}
for {1, 1, 1, 2, 2, 2, 3, 4} ==> {1, 2, 3, 4, 1, 2, 1, 2}
However, i think this is the best spread you can get given the scoring function provided.
Since the dispersion score counts the sum of the distances instead of the squared sum of the distances, you can have several duplicates close together, as long as you have a large gap somewhere else to compensate.
for a sum-of-squared-distances score, the problem becomes harder.
Perhaps the interview question hinged on the candidate recognizing this weakness in the scoring function?
In perl
#a=(9,9,9,2,2,2,1,1,1);
then make a hash table of the counts of different numbers in the list, like a frequency table
map { $x{$_}++ } #a;
then repeatedly walk through all the keys found, with the keys in a known order and add the appropriate number of individual numbers to an output list until all the keys are exhausted
#r=();
$g=1;
while( $g == 1 ) {
$g=0;
for my $n (sort keys %x)
{
if ($x{$n}>1) {
push #r, $n;
$x{$n}--;
$g=1
}
}
}
I'm sure that this could be adapted to any programming language that supports hash tables
python code for algorithm suggested by Vorsprung and HugoRune:
from collections import Counter, defaultdict
def max_spread(data):
cnt = Counter()
for i in data: cnt[i] += 1
res, num = [], list(cnt)
while len(cnt) > 0:
for i in num:
if num[i] > 0:
res.append(i)
cnt[i] -= 1
if cnt[i] == 0: del cnt[i]
return res
def calc_spread(data):
d = defaultdict()
for i, v in enumerate(data):
d.setdefault(v, []).append(i)
return sum([max(x) - min(x) for _, x in d.items()])
HugoRune's answer takes some advantage of the unusual scoring function but we can actually do even better: suppose there are d distinct non-unique values, then the only thing that is required for a solution to be optimal is that the first d values in the output must consist of these in any order, and likewise the last d values in the output must consist of these values in any (i.e. possibly a different) order. (This implies that all unique numbers appear between the first and last instance of every non-unique number.)
The relative order of the first copies of non-unique numbers doesn't matter, and likewise nor does the relative order of their last copies. Suppose the values 1 and 2 both appear multiple times in the input, and that we have built a candidate solution obeying the condition I gave in the first paragraph that has the first copy of 1 at position i and the first copy of 2 at position j > i. Now suppose we swap these two elements. Element 1 has been pushed j - i positions to the right, so its score contribution will drop by j - i. But element 2 has been pushed j - i positions to the left, so its score contribution will increase by j - i. These cancel out, leaving the total score unchanged.
Now, any permutation of elements can be achieved by swapping elements in the following way: swap the element in position 1 with the element that should be at position 1, then do the same for position 2, and so on. After the ith step, the first i elements of the permutation are correct. We know that every swap leaves the scoring function unchanged, and a permutation is just a sequence of swaps, so every permutation also leaves the scoring function unchanged! This is true at for the d elements at both ends of the output array.
When 3 or more copies of a number exist, only the position of the first and last copy contribute to the distance for that number. It doesn't matter where the middle ones go. I'll call the elements between the 2 blocks of d elements at either end the "central" elements. They consist of the unique elements, as well as some number of copies of all those non-unique elements that appear at least 3 times. As before, it's easy to see that any permutation of these "central" elements corresponds to a sequence of swaps, and that any such swap will leave the overall score unchanged (in fact it's even simpler than before, since swapping two central elements does not even change the score contribution of either of these elements).
This leads to a simple O(nlog n) algorithm (or O(n) if you use bucket sort for the first step) to generate a solution array Y from a length-n input array X:
Sort the input array X.
Use a single pass through X to count the number of distinct non-unique elements. Call this d.
Set i, j and k to 0.
While i < n:
If X[i+1] == X[i], we have a non-unique element:
Set Y[j] = Y[n-j-1] = X[i].
Increment i twice, and increment j once.
While X[i] == X[i-1]:
Set Y[d+k] = X[i].
Increment i and k.
Otherwise we have a unique element:
Set Y[d+k] = X[i].
Increment i and k.
I have a set of numbers say : 1 1 2 8 5 6 6 7 8 8 4 2...
I want to detect the duplicate element in sub-array (of given size say k) of the above numbers... For example : Consider the increasing sub arrays for k=3`
Sub array 1 :{1,1,2}
Sub array 2 :{1,2,8}
Sub array 3 :{2,8,5}
Sub array 4 :{8,5,6}
Sub array 5 :{5,6,6}
Sub array 6 :{6,6,7}
....
So my algorithm should detect that sub-arrays 1, 5, and 6 contain duplicates..
My approach :
1)Copy the 1st k elements to a temporary array(vector)
2) using #include file in C++ STL...using unique() I would determine if there's any change in size of vector..
Any other clue how to approach this problem....because my method would consume lot of time and space if the list of the given number is large..
O(n) average time and O(k) space solution could be to build a hash-based histogram, and iterate the array while maintaining #occurances for elements in each sublist.
In each iteration, kick the eldest element out (by decreasing the relevant entrance in the histogram) and add a new element.
Also maintain a numDupes variable, which counts how many dupes you currently have and is maintained when adding/removing elements from the current candidate.
Pseudo code (sorry if I have off by 1 error or something, but this is the idea):
numDupes = 0
histogram = new map<int,int>;
//first set:
for each i form 0 to k:
if histogram.contains(arr[i]):
histogram.put(arr[i],histogram.get(arr[i]) + 1)
numDupes += 1
else:
histogram.put(arr[i],1)
//each iteration is for a new set
if (numDupes > 0) print 1 //first sub array has dupes
for each i from k to n:
if (histogram.get(arr[i-k]) > 1) numDupes -= 1 //we just removed a dupe
histogram.put(arr[i-k],histogram.get(arr[i-k] - 1)) //take off "eldest" element.
if (histogram.contains(arr[i]) && histogram.get(arr[i]) > 0):
histogram.put(arr[i],histogram,get(arr[i]) + 1))
numDupes += 1 //we just added a dupe
else:
histogram.put(arr[i],1)
if (numDupes > 0) print i-k+1 // the current sub array contains a dupe
The initial answer had a small mistake: It failקג to catch cases when the last element added did not cause the dupe, but there is still one (like sub array 6 in the example).
It can be solved by maintaining an extra integer that counts the number of current dupes found, and print the sub-array when the counter is greater then 0. (updated the pseudo code).
Also note: To achieve O(k) space, your histogram needs to delete elements when their value is 0.
How would you implement a random number generator that, given an interval, (randomly) generates all numbers in that interval, without any repetition?
It should consume as little time and memory as possible.
Example in a just-invented C#-ruby-ish pseudocode:
interval = new Interval(0,9)
rg = new RandomGenerator(interval);
count = interval.Count // equals 10
count.times.do{
print rg.GetNext() + " "
}
This should output something like :
1 4 3 2 7 5 0 9 8 6
Fill an array with the interval, and then shuffle it.
The standard way to shuffle an array of N elements is to pick a random number between 0 and N-1 (say R), and swap item[R] with item[N]. Then subtract one from N, and repeat until you reach N =1.
This has come up before. Try using a linear feedback shift register.
One suggestion, but it's memory intensive:
The generator builds a list of all numbers in the interval, then shuffles it.
A very efficient way to shuffle an array of numbers where each index is unique comes from image processing and is used when applying techniques like pixel-dissolve.
Basically you start with an ordered 2D array and then shift columns and rows. Those permutations are by the way easy to implement, you can even have one exact method that will yield the resulting value at x,y after n permutations.
The basic technique, described on a 3x3 grid:
1) Start with an ordered list, each number may exist only once
0 1 2
3 4 5
6 7 8
2) Pick a row/column you want to shuffle, advance it one step. In this case, i am shifting the second row one to the right.
0 1 2
5 3 4
6 7 8
3) Pick a row/column you want to shuffle... I suffle the second column one down.
0 7 2
5 1 4
6 3 8
4) Pick ... For instance, first row, one to the left.
2 0 7
5 1 4
6 3 8
You can repeat those steps as often as you want. You can always do this kind of transformation also on a 1D array. So your result would be now [2, 0, 7, 5, 1, 4, 6, 3, 8].
An occasionally useful alternative to the shuffle approach is to use a subscriptable set container. At each step, choose a random number 0 <= n < count. Extract the nth item from the set.
The main problem is that typical containers can't handle this efficiently. I have used it with bit-vectors, but it only works well if the largest possible member is reasonably small, due to the linear scanning of the bitvector needed to find the nth set bit.
99% of the time, the best approach is to shuffle as others have suggested.
EDIT
I missed the fact that a simple array is a good "set" data structure - don't ask me why, I've used it before. The "trick" is that you don't care whether the items in the array are sorted or not. At each step, you choose one randomly and extract it. To fill the empty slot (without having to shift an average half of your items one step down) you just move the current end item into the empty slot in constant time, then reduce the size of the array by one.
For example...
class remaining_items_queue
{
private:
std::vector<int> m_Items;
public:
...
bool Extract (int &p_Item); // return false if items already exhausted
};
bool remaining_items_queue::Extract (int &p_Item)
{
if (m_Items.size () == 0) return false;
int l_Random = Random_Num (m_Items.size ());
// Random_Num written to give 0 <= result < parameter
p_Item = m_Items [l_Random];
m_Items [l_Random] = m_Items.back ();
m_Items.pop_back ();
}
The trick is to get a random number generator that gives (with a reasonably even distribution) numbers in the range 0 to n-1 where n is potentially different each time. Most standard random generators give a fixed range. Although the following DOESN'T give an even distribution, it is often good enough...
int Random_Num (int p)
{
return (std::rand () % p);
}
std::rand returns random values in the range 0 <= x < RAND_MAX, where RAND_MAX is implementation defined.
Take all numbers in the interval, put them to list/array
Shuffle the list/array
Loop over the list/array
One way is to generate an ordered list (0-9) in your example.
Then use the random function to select an item from the list. Remove the item from the original list and add it to the tail of new one.
The process is finished when the original list is empty.
Output the new list.
You can use a linear congruential generator with parameters chosen randomly but so that it generates the full period. You need to be careful, because the quality of the random numbers may be bad, depending on the parameters.