Paste block multiple times with (increasing) numbering using vim - vim

I have a block in a yaml file that I would like to yank and paste several times:
- probeNumber: 1
probeLocation: [0, 0, 0.1]
Is it possible to automatically increment the value of probeNumber and probeLocation in each block? Like so:
- probeNumber: 1
probeLocation: [0, 0, 0.1]
- probeNumber: 2
probeLocation: [0, 0, 0.15]
- probeNumber: 3
probeLocation: [0, 0, 0.20]
probeLocation is not an integer, it is incremented by a fixed value in each block (0.05). I need 1000 or so of these blocks so doing this manually is not feasible.

Create a template in your text file, suppose starting with line 1.
- probeNumber: 1
probeLocation: [0, 0, 0.1]
- probeNumber: 1
probeLocation: [0, 0, 0.1]
...repeat the number as you want, e.g. copy the first block and do 100p for 100 copy
Then use following command to update the value:
For updating probeNumber
:%s!1$!\=printf("%d", line('.')/3+1)!g
For updating probeLocation
:%s!0\.1!\=printf("%0.2f", 0.10+(line('.')/3)*0.05)!g
Where 0.10 is the initial value, 0.05 is the increment.
Thank for SergioAraujo pointing out mistake of the original expression
:%s!0\.1$!\=printf("0.%d", 10+(line('.')/3)*5)!g
Which fails as the replaced value will never be greater than 1.
The main idea is to use line function to update the value, you may check Replace a pattern with current line number and Insert line numbers for more details.

I have figured out another way of solving this issue:
If you have the three first lines on the clipboard, which means the two first lines and a blank line you could create the file with this:
:for i in range(999) | silent! 0put + | endfor
In order to increase probeNumber lines:
:let c=1 | g/\d\+$/ s//\=c/ | let c+=1
Now the lines with probeLocation:
:let c=0.10 | g/0\.1\ze]/ s//\=printf("%0.2f", c)/ | let c+=0.05

Related

What conversion is being used in these commands-- multiples of 16?

I'm controlling a board that has 16 outputs in two groups #1: 1-8, #2: 9-16.
The first part of the command is the group [1,...] or [2,...]
The second part is the output, so in the limited examples I am shown [1,1,...] would turn on [group 1, channel 1, ....]-- so far so good.
The next example is Output 8: [1, 128, ...]
The next example is Outputs 1 & 8: [1, 129, ...]
What is this conversion called? I'm assuming the outputs map as follows, is this correct:
Output 1 (or 9): 1
Output 2 (or 10): 16
Output 3 (or 11): 32
...
Output 8 (or 16): 128
So if I wanted outputs 2 & 3 the command would be [1, 48]?
You work with bits. 10000000 means turn on output 8. 10000000 in binary means 128 in decimal. If you wanted output 7 you’d do 1000000 which is 64 in decimal. Most programming languages would let you do something like 0x01001100 for example to turn on 7,4 and 3. Easier to work in binary.
The generic formula for you to find the value to set 1 output would be:
second_part = 2^(output_to_set - 1)
For multiple outputs, you just need to add them.
So if you want to set, outputs 2 and 3:
second_part = 2^1 + 2^2 = 6

Python: Increasing one number in a list by one

I am trying to write a program that returns the frequency of a certain pattern. My frequency list is initially a list of zeros, and I want to increase a certain zero by one depending on the pattern. I have tried the code below, but it does not work.
FrequencyArray[j] = FrequencyArray[j]+1
Is there another way to increase one element of the list by 1 without affecting the other elements?
While your approach should work, this would be the alternative:
FrequencyArray[j] += 1
Example:
>>> zeros = [0, 0, 0]
>>> zeros[1] += 1
>>> zeros
[0, 1, 0]

num2str sets a constant width for integer formatting

I am using num2str to print an array of integers. My problem is that the format %d, (notice no flag or field width) doesn't yield a comma-separated list of values as I would expect.
Instead, it seems that all elements are forced to the same width by introducing spaces. I would like to get rid of these spaces. For example:
>> num2str(randi(10,1,10),'%d,')
7, 8,10,10, 2, 2, 7, 1, 6, 6,
>> num2str(randi(10,1,10),'%d,')
9,5,4,7,8,6,4,2,6,3,
In the first example, you can see that all elements have a width of 2 -- this is the largest width among all elements, but I would prefer the output list to be compact: 7,8,10,10,2,2,7,1,6,6,. In the second example, the largest width is 1, and there are no spaces introduced. I don't understand why Matlab would force all elements to have equal field length.
num2str computes the max of the vector, and pads with white space numbers that have less digits (type edit num2str in the command window to see the source code).
Try sprintf instead,
sprintf('%d,', randi(1000,1,10))

How to make a visual selection in vimscript given two (line, col) pairs?

Given the following text in Vim:
ab
cde
And two positions like from (line 1, col 3) to (line 2, col 4), how can I make a visual selection that covers them in Vimscript, including both ends?
Note (line 1, col 3) refers to the position after b, which is usually not selectable in normal mode.
Visual selection bounds are stored in < and > marks. gv in normal mode tells vim to enter visual mode using the < and > marks.
You can use setpos() to set a mark given a position. It expects the mark and a list of (buffer number, line, column, offset). offset is used only with :virtualedit. The current buffer can be chosen using number 0.
call setpos("'<", [0, 1, 3, 0])
call setpos("'>", [0, 2, 4, 0])
normal! gv

Python range() with negative strides

Is there a way of using the range() function with stride -1?
E.g. using range(10, -10) instead of the square-bracketed values below?
I.e the following line:
for y in range(10,-10)
Instead of
for y in [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]:
Obviously one could do this with another kind of loop more elegantly but the range() example would work much better for what I want.
You can specify the stride (including a negative stride) as the third argument, so
range(10,-11,-1)
gives
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
In general, it doesn't cost anything to try. You can simply type this into the interpreter and see what it does.
This is all documented here as:
range(start, stop[, step])
but mostly I'd like to encourage you to play around and see what happens. As you can see, your intuition was spot on.
Yes, by defining a step:
for i in range(10, -11, -1):
print(i)
In addition to the other good answers, there is an alternative:
for y in reversed(range(-10, 11)):
See the documentation for reversed().
You may notice that the range function works only in ascending order without the third parameter. If you use without the third parameter in the range block, it will not work.
for i in range(10,-10)
The above loop will not work.
For the above loop to work, you have to use the third parameter as negative number.
for i in range(10,-10,-1)
Yes, however you'll need to specify that you want to step backwards by setting the step argument to -1.
Use:
for y in range(10, -10, -1)
For your case using range(10,-10,-1)
will be helpful. The first argument refers to the first step, the second one refers to the last step, and the third argument refers to the size of that step.
When your range is ascending, you do not need to specify the steps if you need all numbers between, range(-10,10) or range(-10,-5).
But when your range is descending, you need to specify the step size as -1, range(10,-10,-1) or any other larger steps.
If you prefer create list in range:
numbers = list(range(-10, 10))
To summarize, these 3 are the best efficient and relevant to answer approaches I believe:
first = list(x for x in range(10, -11, -1))
second = list(range(-10, 11))
third = [x for x in reversed(range(-10, 11))]
Alternatively, NumPy would be more efficient as it creates an array as below, which is much faster than creating and writing items to the list in python. You can then convert it to the list:
import numpy as np
first = -(np.arange(10, -11, -1))
Notice the negation sign for first.
second = np.arange(-10, 11)
Convert it to the list as follow or use it as numpy.ndarray type.
to_the_list = first.tolist()
#Treversed list in reverse direction
l1=[2,4,3]
for i in range (len(l1)-1,-1,-1):
print (l1[i])

Resources