How can I use IF and ELSE IF in looping and display 2 statements in GAMS? - optimization

I am a beginner level in this program. I try to improve this loop according to this condition. The details are as follows:
When CUTI(k) = CUTI(k)-4 then,
1)If the result shows this CUTI(k) value greater than 0, then print this CUTI(k) value.
2)If the result shows CUTI(k) value less than 0, then print this CUTI(k) value is added 12 with showing a word "*" after the number in display, e.g. 10*, 9*
I am not sure this loop is correct and enough to add this condition. Look forward to seeing your recoomendation. :)
set k /1*20/;
parameter
CUTI(k)/1 6, 2 2, 3 8, 4 5, 5 1, 6 3, 7 7, 8 8, 9 6, 10 8,11 1, 12 2, 13 4, 14 7,
15 5, 16 2, 17 8, 18 9, 19 2, 20 10/;
loop(k,
if(CUTI(k)-4 > 0,
CUTI(k) = CUTI(k)-4;
else
CUTI(k) = (CUTI(k)-4)+12 ;
)
);
display CUTI;

Your logic looks correct. However, instead of the loop/if/else you could simplify this to one assignment:
CUTI(k) = CUTI(k)-4+12$(CUTI(k)<=4);
However, modifying the display statement by adding a * to some elements is not possible. If you need to distinguish the cases in such a statement, you might assign the values to two different parameters and display them individually.

Related

Conditional replacement of values in a matrix in DolphinDB

For example, matrix A = matrix(1 2 3, 4 5 6, 7 8 9).
How can I replace all the values smaller than 5 with a specified value? The desired output is(5 5 5, 5 5 6, 7 8 9)
You can obtain the result in three different ways in DolphinDB. See the following codeļ¼š
Method 1:
Use function iif
iif(a<5, 5, a)
Method 2:
Use conditional expressions
(a<5) *5 + (a>=5) * a
Method 3:
Use user-defined functions
m=each(def(mutable x){x[x<5]=5;return x},a)

Explain the difference in this while loop please

Example:
x = 0
while x <= 10:
x += 2
print(x)
Results for this will be 0, 2, 4, 6, 8 , 10
If I switch the postion of print(x) and x += 2. The results will be 2, 4, 6, 8, 10, 12.
Please explain to me the thought process for this.
Thanks
I suppose this is Python. Basically the code will get executed in the order it is written. I suggest you to take a sheet of paper and follow the lines of code, trying to figure out what happens and what is the value of your variable at each step. The output will be the values that your variable had when it got printed with the print function.

Moving data labels for two consecutive points

I have been trying to find a way to move data labels either above or below points.
Starting at point 1, for every two consecutive points, I'd like to move the data labels above the point, and for the next 2, I'd like to move them below. I'm not sure how to change my for loop or if statement to accommodate this condition. So in the end, the data labels for points 1 and 2 would be positioned above, the data labels for points 3 and 4 would be positioned below, 5 and 6 above...etc
If anyone can help, I'd greatly appreciate it.
Dim FlowIndex As Long
With ActiveChart.SeriesCollection(1)
For FlowIndex = 1 To .Points.Count
With .Points(FlowIndex)
If .HasDataLabel Then
With .DataLabel
.Position = xlLabelPositionAbove
.Orientation = xlHorizontal
End With
End If
End With
Next
End With
This is a mathematical question of how to perform your loop. Think of the values 1,2,3,4,5,6,7,8. What mathematical rule would put 1,2,5,6 in the same group, and 3,4,7,8 in another group?
Possible answer: when divided by 4, 1 & 2 round down to 0. 3 & 4 round up to 1. 7&8 round up to 3. So, one group rounds up to an even number, and one group rounds down to an odd number. There are many ways to reflect this principle, but here is one:
IF FlowIndex MOD 4 = 1 OR FlowIndex MOD 4 = 2 then 'There is a remainder of 1 or 2 when divided by 4 - put label above
'Do stuff
Else 'There is a remainder of 3 or 0 when divided by 4 - put label below
'Do other stuff
End If
To clarify on my answer to the last question you had, MOD is a method of dividing which returns the remainder after doing whole number division. So 5 MOD 3 is 2, 9 MOD 3 is 0, etc.
Alternatively:
bLabelAbove = True
For i = 0 to 20 step 2
For j = 1 to 2
If bLabelAbove Then
Series.DataLabels(i + j).Position = xlLabelPositionAbove
Else
Series.DataLabels(i + j).Position = xlLabelPositionBelow
End If
Next
bLabelAbove = Not bLabelAbove
Next
Divide
1, 2, 3, 4, 5, 6, 7, 8
by 2, and round up, to get:
1, 1, 2, 2, 3, 3, 4, 4
Then you can test whether1, 1, 2, 2, 3, 3, 4, 4 is odd or even. If odd, then label above. If even, then label below.

Delete every other line starting with a 1

I can find sed solutions to delete all lines in a text file starting with a '1' as well as solutions to delete every other line of all the lines in the text file but I want to combine the two.. of all the lines starting with '1' delete every other one of them and keep the other lines that do not start with a 1.
So if I have a text file:
1, 1
1, 2
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
1, 9
4, 10
I want the output to be:
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
You could do this in awk:
awk -F, '!($1 == 1 && n++ % 2)' file
-F, means use comma as the field separator, so the two numbers on each line will be the variables $1 and $2.
awk will print the line if the last thing it evaluates is true. The ! negates the contents of the parentheses, so in order to print, the contents must be false.
If the first field isn't 1, short-circuiting takes place, as (false && anything) will always be false. This means that the second half after the && will not be evaluated.
If $1 == 1, then the second half is evaluated. As n is being used for the first time in a numeric context, it will assume the value 0. The modulo operation n % 2 will return 0 (false) for even numbers and 1 (true) for odd numbers. Using the increment n++ means that the result will alternate between true and false.
You may prefer the reverse logic, which would be:
awk -F, '$1 != 1 || ++n % 2' file
The || is also short-circuiting, so if the first value isn't 1 then the line gets printed. Otherwise, the second half is evaluated. This time, the increment goes before the n so that the first value of n is 1, making the expression evaluate to true.
Either way, the output is:
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
This might work for you (GNU sed):
sed '/^1/{x;/./{z;x;d};x;h}' file
Use the hold space to toggle the deletion of lines beginning with 1.
An alternative:
sed '/^1/{:a;n;//d;ba}' file
Here you go:
awk '$1=="1," && !(f=f?0:1) {next} 1' file
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
$1=="1," Test if first field is 1
f=f?0:1 Flop the f between 0 and 1 for every time $1=="1," is true
!(...) True if f is 0
Here's an awk-based solution without requiring any modulo math whatsoever :
[ngm]awk 'FS~NF||_*=--_' FS='^1'
|
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
This leverages the interesting property that x *= --x generates an alternating sequence of 1s and 0s that never converges and never diverges.

Step through range in D

Is there a way to create a step in D ranges?
For example, in python,
range(1, 10, 2)
gives me
[1, 3, 5, 7, 9]
all odds within 1 .. 10
Is there a way to do this in D using foreach?
foreach(x; 1 .. 10) {
}
I know I can use iota(start, end, step), but I also want to add an int to the very beginning and I don't know how to convert type Result to an int.
chain([2],iota(3,16,2));
chain concatenates ranges lazily
or you can go the other way around with filter!q{a==2||a&1}(iota(2,16));