I am trying to implement an algorithm that is specified using some C style pseudocode.
The bulk of the algorithm is a for loop:
for (i = 20;i > 0;i -= 2)
{
//...snip
}
It is claimed that the loop runs ten times:
The entire series of modifications is a series of 10 identical double-rounds.
I've ported the algorithm to my own language, and my results do not match the test vectors. So i'm trying to pick apart the minutia of the C-language in order to figure out what i could be doing wrong.
Perhaps the reason my code does not match the result of the test vectors is that it is supposed to only run nine times:
| i | i -= 2 | i > 0 | Perform iteration |
|----|--------|-------|-------------------|
| 20 | 18 | Yes | Yes - 1 |
| 18 | 16 | Yes | Yes - 2 |
| 16 | 14 | Yes | Yes - 3 |
| 14 | 12 | Yes | Yes - 4 |
| 12 | 10 | Yes | Yes - 5 |
| 10 | 8 | Yes | Yes - 6 |
| 8 | 6 | Yes | Yes - 7 |
| 6 | 4 | Yes | Yes - 8 |
| 4 | 2 | Yes | Yes - 9 |
| 2 | 0 | No | No |
If i were to read the if statement logically, it is only executed nine times.
There's still the confusion of why they say it runs ten rounds, but then use 20 as the initial value.
I tried duplicating the logic i see (execute it one less times than documented), but my results still don't match. Unfortunately i don't have access to any functional code to compare my results against a known good implementation. So i may be barking up the wrong tree.
Am i barking up the wrong tree?
The third part of the for condition is executed after the iteration.
The loop runs 10 times with i being 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 for the body of each iteration.
A for loop goes "initialization, test, body, increment, test, body, increment, test, body, etc." The increment isn't applied before the first test.
As an aside, if you want to go from the last to the first element in a for loop but don't want the ugly:
for (let i = arr.length - 1; i >= 0; i--)
You can use:
for (let i = arr.length; i-- > 0;)
Example:
const arr = ['a', 'b', 'c'];
for (let i = arr.length; i-- > 0;) {
console.log(`arr[${i}] is: ${arr[i]}`);
}
Had you used pre-decrement here, the last iteration (which is the first element of the array) would have been missing:
const arr = ['a', 'b', 'c'];
for (let i = arr.length; --i > 0;) {
console.log(`arr[${i}] is: ${arr[i]}`);
}
Related
I have a hierarchy-based event stream, where each hierarchy parent node(represented as level0/1) has multiple children (level0(0/1/2) and sub child (level00(0/1/2)). "level" is just a placeholder, each hierarchy level has its own unique name. The only rule is that a parent node hierarchy string is always included in the child's hierarchy string name. Assume that this event stream has 300k and more entries.
| index | hierarchystr |
| ----- | --------------------- |
| 0 | level0level00level000|
| 1 | level0level01 |
| 2 | level0level02level021|
| 3 | level0level02level021|
| 4 | level0level02level020|
| 5 | level0level02level021|
| 6 | level1level02level021|
| 7 | level1level02level021|
| 8 | level1level02level021|
| 9 | level2level02level021|
Now I want to do an inclusive group_by by a separate list and the line should be included if the string in the array is included in the string of the hierarchystr column, expected output (beware hstrs is every time in a different order!):
#hstrs = ["level0", "level1", "level0level01", "level0level02", "level0level02level021"]
|index| 0 | Count |
|-----|---------------------|-------|
|0 |level0 | 6 |
|1 |level1 | 3 |
|2 |level0level01 | 1 |
|3 |level0level02 | 4 |
|4 |level0level02level021| 3 |
I tried the following solutions, but all are slow as hell:
#V1
for hstr in hstrs:
s = df[df.hierarchystr.str.contains(hstr)]
s2 = s.count()
s3 = s2.values[0]
if s3 > 200:
beforeset.append(hstr)
#V2
for hstr in hstrs:
s = df.hierarchystr.str.extract('(' + hstr + ')', expand=True)
s2 = s.count()
s3 = s2.values[0]
if s3 > 200:
list.append(hstr)
#V3 - fastest, but also slow and not satisfying
containing =[item for hierarchystr in df.hierarchystr for item in hstrs if item in hierarchystr]
containing = Counter(containing)
df1 = pd.DataFrame([containing]).T
nodeNamesWithOver200 = df1[df1 > 200].dropna().index.values
I also tried versions for all variables at once with pat and extract, but in return the size per group changes in every run, because the list hstrs is every run in a different order.
df.hierarchystr.extract[all](pat="|".join(hstrs))
Is there a regex and method possible that do this task in one step so this is also applicable for huge data frames at an appropriate time - that not depending on the order of the hstrs array?
You can try:
count = [df['hierarchystr'].str.startswith(hstr).sum() for hstr in hstrs]
out = pd.DataFrame({'hstr': hstrs, 'count': count})
print(out)
# Output
hstr count
0 level0 6
1 level1 3
2 level0level01 1
3 level0level02 4
4 level0level02level021 3
I have a table like this:
| a | b | c |
x | 1 | 8 | 6 |
y | 5 | 4 | 2 |
z | 7 | 3 | 5 |
What I want to do is finding a value based on the row and col titles, so for example if I have c&y, then it should return 2. What function(s) should I use to do this in OpenOffice Calc?
later:
I tried =INDEX(B38:K67;MATCH('c';B37:K37;0);MATCH('y';A38:A67;0)), but it writes invalid argument.
It turned out I wrote the arguments of INDEX in the wrong order. The =INDEX(B38:K67;MATCH('y';A38:A67;0);MATCH('c';B37:K37;0)) formula works properly. The second argument is the row number and not the col number.
I have a variable num with values 1-10.
I would like to create a new variable type with values odd or even:
generate type = odd if inlist(num, 1,3,5,7,9)
Questions:
What is the cleanest way to also label even numbers?
Could I use a negation somewhere and keep the command all in one line?
The code you provide is not valid syntax:
clear
set obs 10
generate num = _n
generate type = odd if inlist(num, 1,3,5,7,9)
odd not found
r(111);
You could get what you want with:
generate type = "odd" if inlist(num, 1,3,5,7,9)
And you can do both at the same time using the cond() function:
generate type = cond(inlist(num, 1,3,5,7,9), "odd", "even")
However, having this variable as a string will be of limited value for later use.
You could subsequently use the encode command to create a new variable of numeric type:
encode type, generate(type2)
list
+--------------------+
| num type type2 |
|--------------------|
1. | 1 odd odd |
2. | 2 even even |
3. | 3 odd odd |
4. | 4 even even |
5. | 5 odd odd |
|--------------------|
6. | 6 even even |
7. | 7 odd odd |
8. | 8 even even |
9. | 9 odd odd |
10. | 10 even even |
+--------------------+
Although seemingly identical, type and type2 variables are indeed of a different type:
list, nolabel
+--------------------+
| num type type2 |
|--------------------|
1. | 1 odd 2 |
2. | 2 even 1 |
3. | 3 odd 2 |
4. | 4 even 1 |
5. | 5 odd 2 |
|--------------------|
6. | 6 even 1 |
7. | 7 odd 2 |
8. | 8 even 1 |
9. | 9 odd 2 |
10. | 10 even 1 |
+--------------------+
This is how you can do it with type being a numeric variable:
generate type = mod(num, 2)
list
+------------+
| num type |
|------------|
1. | 1 1 |
2. | 2 0 |
3. | 3 1 |
4. | 4 0 |
5. | 5 1 |
|------------|
6. | 6 0 |
7. | 7 1 |
8. | 8 0 |
9. | 9 1 |
10. | 10 0 |
+------------+
You then create the value label and attach it to the variable type:
label define numlab 0 "even" 1 "odd"
label values type numlab
list
+------------+
| num type |
|------------|
1. | 1 odd |
2. | 2 even |
3. | 3 odd |
4. | 4 even |
5. | 5 odd |
|------------|
6. | 6 even |
7. | 7 odd |
8. | 8 even |
9. | 9 odd |
10. | 10 even |
+------------+
If you only want the odd numbers labeled you can simply do:
label define numlab 1 "odd"
If you later change your mind and want to add a label for even numbers:
label define numlab 0 "even", add
When your command has been run, the value of type for the odd numbers is "odd" and the value for the even numbers is "", that is a missing string.
You could tag the even numbers using
replace type = "even" if type==""
I cannot think of a way to keep it all in one line, since you have to both generate the variable and fill in two different string values.
If you could use a numeric variable (I name it flag) as your type variable, you could try this:
gen flag = mod(num,2)
This will flag the odd numbers as 1 and the even numbers as 0. You could then create a label for the flag variable, if you need to display its values as "odd" and "even".
So I'm trying to figure out a good way of vectorizing a calculation and I'm a bit stuck.
| A | B (Calculation) | B (Value) |
|---|----------------------|-----------|
| 1 | | |
| 2 | | |
| 3 | | |
| 4 | =SUM(A1:A4)/4 | 2.5 |
| 5 | =(1/4)*A5 + (3/4)*B4 | 3.125 |
| 6 | =(1/4)*A6 + (3/4)*B5 | 3.84375 |
| 7 | =(1/4)*A7 + (3/4)*B6 | 4.6328125 |
I'm basically trying to replicate Wilder's Average True Range (without using TA-Lib). In the case of my simplified example, column A is the precomputed True Range.
Any ideas of how to do this without looping? Breaking down the equation it's effectively a weighted cumulative sum... but it's definitely not something that the existing pandas cumsum allows out of the box.
This is indeed an ewm problem. The issue is that the first 4 rows are crammed together into a single row... then ewm takes over
a = df.A.values
d1 = pd.DataFrame(dict(A=np.append(a[:4].mean(), a[4:])), df.index[3:])
d1.ewm(adjust=False, alpha=.25).mean()
A
3 2.500000
4 3.125000
5 3.843750
6 4.632812
I am trying to put a new item to vector, and shift remaining items. How can I do that ?
Ex
vector -------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 9 | 10 | 15 | 21 | 34 | 56 | 99 |
-------------------------------------------------------
^
new item = 14, it should be added to ^
After insertion,
vector ------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 21 | 34 | 56 | 99 |
------------------------------------------------------------
^ ^
^-shifted to right by one-^
Check the vector::insert() function.
vector<int> vec ;
// Add elements to vec
vec.insert(vec.begin() + position, new_item);
Use insert.
vector<int> v {1,2,3,5};
v.insert (v.begin() + 3, 4); //v is now {1,2,3,4,5}
You can also insert ranges of elements and other cool stuff, similar to the vector constructor.
if you don't know the exact position you want to insert it then vec.insert() is not going to work well.
vec.push_back(15);
std::sort(vec.begin(), vec.end());