How to create a script that would calculate the difference between samples in a list? - powershell

I am trying to create a script that would calculate the difference between samples in a list.
If we take this example:
- result1 = 33
- result2 = 45
- result3 = 66
- result4 = 47
- result"n" = 50
The calculus should start at the second result from the list and descend until the last result, and then sum up those results:
result2 - result1 = 12,
result3 - result2 = 21,
result4 - result3 = 19,
result"n" - result4= 3
sum = 12 + 21 + 19 + 3 = 55
I am new at scripting, and so far i only came up with this solution:
$numbers
$1=[math]::abs($numbers[0]-$numbers[1])
$2=[math]::abs($numbers[1]-$numbers[2])
$3=[math]::abs($numbers[2]-$numbers[3])
$4=[math]::abs($numbers[3]-$numbers[4])
write-host "the results = $1, $2, $3, $4"
$sum = $1 + $2 + $3 + $4
The problem is that the list is dynamic and changes in length, one time there are 10 results and one time 20 for example.
I found a similar question here, but i don't know how to implement the solution to my case, as that is too complicated for me.

What you need is a For loop. It is structured as such:
For(<initial declaration, usually a start point like $i = 0>; <Condition to stop when false>;<Action to perform on each iteration to progress loop>){
Code to perform on each loop
}
For you we would do something like:
For($i=1;$i -le $numbers.count;$i++)
That starts 1, and since arrays start at 0 this will get you going with the second record. Then in the scriptblock we do something like:
{
[array]$Results += [math]::abs($numbers[$i] - $numbers[($i-1)])
}
That will get the differences for you, then to display them you can do something like:
"the results = " + ($Results -join ", ")
$sum = $Results|Measure -sum|select -expand Sum
So you put that all together and get
For($i=1;$i -le $numbers.count;$i++){
[array]$Results += [math]::abs($numbers[$i] - $numbers[($i-1)])
}
"the results = " + ($Results -join ", ")
$sum = $Results|Measure -sum|select -expand Sum

Use a for loop, use the length of your $numbers array to know when to stop.
$numbers = #(33,45,66,47,50)
$sum = 0
for($cur=1;$cur -lt $numbers.Length; $cur += 1){
$sum += [math]::abs($numbers[$cur]-$numbers[$cur-1]);
}
$sum

Related

Calculate two audio duration with frame

I am stuck, I need a small logic.
I have two audio durations
x = "00:00:07:18"
y = "00:00:06:00" H : M: S: F
Answer should be x + y = 00:00:13:18
H=hours S= seconds M=minutes F=frame
My question is
if x = "00:00:03:14"
y = "00:00:13:18"
answer should be x + y = **00:00:17:02**
If the frame is greater than 30 it should increase 1 in second.
I am using power shell. How can I determine the logic to calculate both of this?
Calculation of the first 3 parts (hour:minute:second), we can offload to the [timespan] type, then all we need to worry about is carrying excess frames over:
# Simple helper function to turn our input strings into a [timespan] + frame count
function Parse-FrameDuration
{
param(
[string]$Duration
)
$hour,$minute,$second,$frame = ($Duration -split ':') -as [int[]]
[PSCustomObject]#{
Time = New-TimeSpan -Hours $hour -Minutes $minute -Seconds $second
Frame = $frame
}
}
# function to do the actual calculation
function Add-Frame
{
param(
[string]$Base,
[string]$Offset
)
# Parse our two timestamps
$a = Parse-FrameDuration $Base
$b = Parse-FrameDuration $Offset
# Calculate frames % frame rate, remember to carry any excess seconds
$frames = 0
$carry = [math]::DivRem($a.Frame + $b.Frame , 30, [ref]$frames)
# Calculate time difference, add any extra second carried from frame count
$new = ($a.Time + $b.Time).Add($(New-TimeSpan -Seconds $carry))
# Stitch output string together from new timespan + remaining frames
return "{0:hh\:mm\:ss}:{1:00}" -f $new,$frames
}
Now we can do:
PS C:\> Add-Frame -Base 00:00:03:14 -Offset 00:00:13:18
00:00:17:02

Split an array based on value

This is my first question here, so sorry if I make any mistakes posting this.
I'm trying to split an array based on its values. Basically I want to create two arrays whose values are as close to the average as possible. I managed to do this with this code:
function Sum($v) {
[Linq.Enumerable]::Sum([int64[]]$v)
}
$arr = 0..9 | % {get-random -min 1 -max 10}
"ARRAY:" + $arr
"SUM: " + (sum $arr)
"AVG: " + (sum $arr)/2
# start of the code that matters
$wavg = (sum $arr)/2
foreach ($i in (0..($arr.Count-1))) {
$wavg -= $arr[$i]
if ($wavg -le 0) {
$i-=(-$wavg -gt $arr[$i]/2);break
}
}
"SPLIT INDEX: " + $i
"ARR1: " + $arr[0..$i] + " (" + $(sum $arr[0..$i]) + ")"
"ARR2: " + $arr[($i+1)..$arr.Count] + " (" + $(sum $arr[($i+1)..$arr.Count]) + ")"
The reason my foreach is structured this way is because in my actual code the values are in an index hash and are accessed as $index[$arr[$i]].
This means that the resulting two arrays could be of unequal size (it would be easy if I could just split the array in half). Sample output of my code to demonstrate this:
ARRAY: 5 3 6 3 2 3 6 3 1 3
SUM: 35
AVG: 17.5
SPLIT INDEX: 3
ARR1: 5 3 6 3 (17)
ARR2: 2 3 6 3 1 3 (18)
The code works as is, but I feel it could be done in a more elegant and speedier way. Because I need to execute this code a few thousand times in my script I want it to be as fast as possible.

Calculate result based on percentage in Powershell

I want to calculate the following in Powershell
$x = 100
$y = 25
result = x * y%
Should be really simple, but I can't seem to come up with the right way to calculate the correct result in Powershell
Divide by 100 to get the percentage:
$x = 100
$y = 25
$result = $x * ($y / 100)

PowerShell HashTable - self referencing during initialization

I have a theoretical problem - how to reference a hash table during its initialization, for example, to compute a member based other already stated members.
Remove-Variable myHashTable -ErrorAction Ignore
$myHashTable =
#{
One = 1
Two= 2
Three = ??? # following expressions do not work
# $This.One + $This.Two or
# $_.One + $_.Two
# $myHashTable.One + $myHashTable.Two
# ????
}
$myHashTable.Three -eq 3 # make this $true
Any ideas how to do it? Is it actually possible?
Edit:
This was my solution:
$myHashTable =
#{
One = 1
Two= 2
}
$myHashTable.Three = $myHashTable.One + $myHashTable.Two
This won't be possible using the object initializer syntax I'm afraid. While it is possible to use variables, you'll have to compute the values before creating the object.
I cannot recommend this, but you can iterate the initializer twice or more:
(0..1) | %{
$a = #{
One = 1
Two = $a.One + 1
}
}
(0..2) | %{
$b = #{
One = 1
Two = $b.One + 1
Three = $b.Two + 1
}
}
Make sure all calculations are idempotent, i.e. do not depend on a number of iterations.
You can also recur to this...
sometimes when the hashtable is very long
and can be defined only in 2 or three recurrences...
works fine:
$AAA = #{
DAT = "C:\MyFolderOfDats"
EXE = "C:\MyFolderOfExes"
}
$AAA += #{
Data = $AAA.DAT + "\#Links"
Scripts = $AAA.EXE + "\#Scripts"
ScriptsX = $AAA.EXE + "\#ScriptsX"
}
Note in the second part we are just adding ( += ) more items to the first part... but now... we can refer the items in first part
of the hashtable

Why is a big loop within a small loop faster than a small loop within a big one?

This is my Perl code
$big=10_000_000;
#A:big loop outside
my $begin_time = time;
foreach my $i (1..$big) {
foreach my $p (1..10){
}
}
my $end_time = time;
my $t1=$end_time-$begin_time;
#B:small loop outside
my $begin_time = time;
foreach my $i (1..10){
foreach my $p (1..$big){
}
}
my $end_time = time;
my $t2=$end_time-$begin_time;
#output
print $t1;
print "\n";
print $t2;
t1=8 seconds
t2=3 seconds
And the mathematica code:
Timing[Do[2, {i, 1, 10}, {j, 2*1, 10^7}]]
output:{14.328, Null}
Timing[Do[2, {j, 1, 2*10^7}, {i, 1, 10}]]
output:{30.937, Null}
Why does the big loop outside take more time?
There's a certain amount of overhead in executing the inner loop (initialising the variable; making the checks to see if it should end) and in the first case, you are losing this overhead 10,000,000 times; in the second, you are only doing it 10 times.
EDIT:
Let s be the time to setup a loop (e.g. initialise a variable) and i the time to iterate a loop (e.g. test the end condition). Then:
Big Inner Loop
T = s1 + 10 * ( i1 + s2 + 10,000,000*i2 )
= s1 + 10*i1 + 10*s2 + 100,000,000*i2
Big Outer Loop
T = s1 + 10,000,000 * ( i1 + s2 + 10*i2 )
= s1 + 10,000,000*i1 + 10,000,000*s2 + 100,000,000*i2
Difference
diff = 9,999,990*i1 + 9,999,990*s2
So the iteration time of the outer loop (i1) and the set-up time of the inner-loop (s2) are both performed 9,999,990 times more with the big outer loop than with the big inner loop.