Related
In pine script I'm calling a function that sums the previous bar value with an increment:
myFunction(myVar1) =>
var int myVar2 = 0
myVar2 := myVar1 + nz(myVar2[1],1)
The increment value is added using a loop that calls the function and the result is stored in an array:
myArray = array.new_int(0)
var int myVar1 = 1
myVar1 := 1
while myVar1 <= 3
array.push(myArray, myFunction(myVar1))
myVar1 += 1
The result in the first bar was expected. Since there is no previous bar the previous value is replaced by 1 nz(myVar2[1],1)
plot(myArray.get(myArray, 0))
plot(myArray.get(myArray, 1))
plot(myArray.get(myArray, 2))
Result: [2, 3, 4]
But in the second bar:
Result: [5, 6, 7]
My expected result: [3, 5, 7]
Since it runs the loop for the first bar first and then runs the loop again in the second bar it uses for myVar2[1] the last value 4 saved when running the last loop in the first bar.
How can the previous bar values be stored correctly when using a loop so that the expected results can be achieved:
First bar: [2, 3, 4]
Second bar: [3, 5, 7]
Third bar: [4, 7, 10]
Answer to your comment: You could save the current array in another array. That way, you always have access to the array values of the previous bar.
//#version=5
indicator("My Script", overlay=false)
var int myVar1 = na
var int[] myArray = array.new_int(3) // Current array
var int[] prevArray = array.new_int(3) // Previous array
myFunction(myVar1) =>
var int myVar2 = 0
myVar2 := myVar1 + nz(myVar2[1],1)
myVar1 := 1
prevArray := array.copy(myArray) // Save current array
array.clear(myArray) // Clear current array
while myVar1 <= 3
array.push(myArray, myFunction(myVar1))
myVar1 += 1
// Show previous array
plot(array.get(prevArray, 0), 'prevArray[0]')
plot(array.get(prevArray, 1), 'prevArray[1]')
plot(array.get(prevArray, 2), 'prevArray[2]')
// Show current array
plot(array.get(myArray, 0), 'myArray[0]')
plot(array.get(myArray, 1), 'myArray[1]')
plot(array.get(myArray, 2), 'myArray[2]')
I am trying to rotate an array from a particular position using array reversal method.
Input array: [1,2,3,4,5,6,7]
d = 3
Output array: [5,6,7,1,2,3,4]
To achieve this I thought of working on the array in three steps.
Step1: Reverse the array from starting position until d => [4,3,2,1,5,6,7]
Step2: Reverse the array from d till the end of the array => [4,3,2,1,7,6,5]
Step3: Reverse the complete array from Step2 => [5,6,7,1,2,3,4]
I haven't followed any functional programming pattern as I want to check the algorithm step by step.
val arr = Array[Int](1, 2, 3, 4, 5, 6, 7)
def reverseAlgo(brr: Array[Int], start: Int, end: Int): Unit = {
var temp = 0
for(i <- start until end/2) {
temp = brr(i)
brr(i) = brr(end-i-1)
brr(end-i-1) = temp
}
brr.foreach(println)
}
Step1 is working fine:
reverseAlgo(arr, 0, 3)
Output:
3
2
1
4
5
6
7
But Step2 is not producing the required output:
reverseAlgo(arr, 3, 7)
Output:
3
2
1
4
5
6
7
As you see, the output of the array should be: 3,2,1,7,6,5,4
Since the output from Step2 is incorrect, the final output is also wrong.
Step3:
reverseAlgo(arr, 0, arr.length)
Output:
7
6
5
4
1
2
3
Could anyone let me know what is the mistake I am doing here ?
Why not just something as simple as this?
import scala.collection.immutable.ArraySeq
import scala.reflect.ClassTag
def rotate[T : ClassTag](arr: ArraySeq[T])(pos: Int): ArraySeq[T] = {
val length = arr.length
ArraySeq.tabulate[T](n = length) { i =>
arr((i + 1 + pos) % length)
}
}
Which can be used like this:
rotate(arr = ArraySeq(1, 2, 3, 4, 5, 6, 7))(pos = 3)
// res: ArraySeq[Int] = ArraySeq(, 5, 6, 7, 1, 2, 3, 4)
You can see the code running here.
Your code will only work when the range starts at zero.
for(i <- start until end/2) {
temp = brr(i)
brr(i) = brr(end-i-1)
brr(end-i-1) = temp
}
Should be something like:
for(i <- 0 until (end-start)/2) {
temp = brr(start+i)
brr(start+i) = brr(end-i-1)
brr(end-i-1) = temp
}
With this change your code works.
Mutation is to be avoided but, if you must, recursion is still useful.
def reversePart[A](arr: Array[A], start: Int, end: Int): Unit = {
def loop(a:Int, b:Int): Unit =
if (a < b) {
val temp = arr(a)
arr(a) = arr(b)
arr(b) = temp
loop(a+1, b-1)
}
loop(start max 0, end min arr.length-1)
}
val test = Array(1, 2, 3, 4, 5, 6, 7)
reversePart(test, 0, 3) //Array(4, 3, 2, 1, 5, 6, 7)
reversePart(test, 4, 7) //Array(4, 3, 2, 1, 7, 6, 5)
reversePart(test, -1, 99) //Array(5, 6, 7, 1, 2, 3, 4)
I realize this doesn't directly answer your question, but for reference and for readers interested in a slightly different approach, one possibility is to implement this as a view.
In this example, Rotate implements the logic, while IndexedSeqViewRotate adds the rotate method as an extension to any IndexedSeqView as long as it's in scope.
In the tests, I materialized the views into Vectors to take advantage of the equality, but of course you can materialize them into an Array as well.
import scala.collection.IndexedSeqView
import scala.collection.IndexedSeqView.SomeIndexedSeqOps
final class Rotate[A](underlying: SomeIndexedSeqOps[A], n: Int) extends IndexedSeqView[A] {
#inline private def rotateIndex(i: Int): Int = ((i - n) % length + length) % length
override def apply(i: Int): A = underlying(rotateIndex(i))
override lazy val length: Int = underlying.length
}
final implicit class IndexedSeqViewRotate[A](val underlying: IndexedSeqView[A]) extends AnyVal {
def rotate(n: Int): IndexedSeqView[A] = new Rotate(underlying, n)
}
assert(Array().view.rotate(7).to(Vector) == Vector.empty)
assert(Array(1,2,3,4,5,6,7).view.rotate(7).to(Vector) == Vector(1,2,3,4,5,6,7))
assert(Array(1,2,3,4,5,6,7).view.rotate(0).to(Vector) == Vector(1,2,3,4,5,6,7))
assert(Array(1,2,3,4,5,6,7).view.rotate(1).to(Vector) == Vector(7,1,2,3,4,5,6))
assert(Array(1,2,3,4,5,6,7).view.rotate(3).to(Vector) == Vector(5,6,7,1,2,3,4))
assert(Array(1,2,3,4,5,6,7).view.rotate(-1).to(Vector) == Vector(2,3,4,5,6,7,1))
You can play around with this code here on Scastie.
I have troubles using a function in Perl.
My function has 2 arguments which are arrays :
sub get_coordinate {
my (#array_col, #array_lin) = (#_);
do some stuff
}
I call it this way :
$index_col = int(rand(10));
$index_lin = int(rand(10));
#array_col = (0,0,0,0,0,0,0,0,0,0);
#array_lin = (0,0,0,0,0,0,0,0,0,0);
$array_col[$index_col] = 1;
$array_lin[$index_lin] = 1;
get_coordinate(#array_col, #array_lin);
My problem is that I get the error message : Use of uninitialized value within #array_lin in numeric eq (==) at
switch.pl line 82 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
I don't understand why #array_col is initialized an not #array_lin.
When I print #array_col and #array_lin inside the function this way :
print "#array_col\n#array_lin\n";
I get : 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0
Any idea ?
Thx,
SLP
In Perl, all lists are flat. These two lists are equivalent.
( 1, 2, ( 3, 4, ( 5 ), (6, 7), 8), (), )
( 1, 2, 3, 4, 5, 6, 7, 8 )
The same thing also happens when take several arrays and stick them in a list.
my #foo = (1, 2, 3);
my #bar = (4, 5, 6);
my #new = (#foo, #bar); # 1, 2, 3, 4, 5, 6
When you pass things to a function, those things get turned into a list of arguments. Therefore, the arrays will both end up in one list, like #foo and #bar above.
frobnicate(#foo, #bar);
When you assign something in list context, the entire list will be assigned left to right. For scalars in the list on the left-hand-side this means they will get their values. But as soon as there is an array, this will be greedy. It will suck up all the remaining values.
my ($one, $two, #rest, $will_be_undef) = (1, 2, 3, 4, 5, 6);
The values will be assigned like this:
$one = 1;
$two = 2;
#rest = ( 3, 4, 5, 6 );
$will_be_undef = undef;
What you need to do to pass two arrays is to take references, and dereference them in our function.
frobnicate( \#foo, \#bar );
sub frobnicate {
my ($first_array, $second_array) = #_;
my #foo = #{ $first_array };
my #bar = #{ $second_array };
...
}
Assigning to several arrays (or hashes) doesn't do what you think:
my (#array1, #array2) = ...
The first array gets all the elements. How should it know where to stop?
You can use array references instead:
sub get_coordinate {
my ($arr1, $arr2) = #_;
my #arr1 = #$arr1;
my #arr2 = #$arr2;
...
}
get_coordinate(\#array1, \#array2);
Assume that I have an array like 1 2 3 4 5, I want to rotate it to the left by n and get a new one.
For example the 2 rotation of the above array will result in 3 4 5 1 2. I didn't found any extension function to do that.
You can use built-in java Collections.rotate method, but you need to convert your array to list firstly:
val arr = intArrayOf(1, 2, 3, 4, 5)
val list = arr.toList()
Collections.rotate(list, -2)
println(list.toIntArray().joinToString())
Outputs
3, 4, 5, 1, 2
I interpret "get a new one" to mean that the extension function should return a new array instance, like so (boundary checks omitted, sliceArray is an stdlib function) :
fun <T> Array<T>.rotate(n: Int) =
let { sliceArray(n until size) + sliceArray(0 until n) }
Example
arrayOf(1, 2, 3, 4, 5).rotate(1)
.also { println(it.joinToString()) } // 2, 3, 4, 5, 1
Another extension function, by slicing the array in 2 parts left and right and reassembling it to right + left:
fun <T> Array<T>.leftShift(d: Int) {
val n = d % this.size // just in case
if (n == 0) return // no need to shift
val left = this.copyOfRange(0, n)
val right = this.copyOfRange(n, this.size)
System.arraycopy(right, 0, this, 0, right.size)
System.arraycopy(left, 0, this, right.size, left.size)
}
so this:
val a = arrayOf(1, 2, 3, 4, 5, 6, 7)
a.leftShift(2)
a.forEach { print(" " + it) }
will print
3 4 5 6 7 1 2
Simple solution:
fun <T> Array<T>.rotateLeft(n: Int) = drop(n) + take(n)
fun <T> Array<T>.rotateRight(n: Int) = takeLast(n) + dropLast(n)
The limitation is that n must be less than or equal to the length of the array.
Alternatively, you can use Collections.rotate(...) as follows.
import java.util.Collections
fun <T> Array<T>.rotate(distance: Int) =
toList().also { // toList() is a deep copy to avoid changing the original array.
Collections.rotate(it, distance)
}
fun main() {
val xs = arrayOf(1, 2, 3, 4, 5)
val ys = xs.rotate(-2)
xs.forEach { print("$it ") } // 1 2 3 4 5
println(ys) // [3, 4, 5, 1, 2]
}
For the record, you can use the regular Array constructor to build a new array:
inline fun <reified T> Array<T>.rotate(n: Int) = Array(size) { this[(it + n) % size] }
The element at index it in the source array is copied in the destination array at the new index (it + n) % size to perform the rotation.
It is a bit slower than copying the array by chunks.
Let's say I am trying to remove elements from array a = [1,1,1,2,2,3]. If I perform the following:
b = a - [1,3]
Then I will get:
b = [2,2]
However, I want the result to be
b = [1,1,2,2]
i.e. I only remove one instance of each element in the subtracted vector not all cases. Is there a simple way in Ruby to do this?
You may do:
a= [1,1,1,2,2,3]
delete_list = [1,3]
delete_list.each do |del|
a.delete_at(a.index(del))
end
result : [1, 1, 2, 2]
[1,3].inject([1,1,1,2,2,3]) do |memo,element|
memo.tap do |memo|
i = memo.find_index(e)
memo.delete_at(i) if i
end
end
Not very simple but:
a = [1,1,1,2,2,3]
b = a.group_by {|n| n}.each {|k,v| v.pop [1,3].count(k)}.values.flatten
=> [1, 1, 2, 2]
Also handles the case for multiples in the 'subtrahend':
a = [1,1,1,2,2,3]
b = a.group_by {|n| n}.each {|k,v| v.pop [1,1,3].count(k)}.values.flatten
=> [1, 2, 2]
EDIT: this is more an enhancement combining Norm212 and my answer to make a "functional" solution.
b = [1,1,3].each.with_object( a ) { |del| a.delete_at( a.index( del ) ) }
Put it in a lambda if needed:
subtract = lambda do |minuend, subtrahend|
subtrahend.each.with_object( minuend ) { |del| minuend.delete_at( minuend.index( del ) ) }
end
then:
subtract.call a, [1,1,3]
A simple solution I frequently use:
arr = ['remove me',3,4,2,45]
arr[1..-1]
=> [3,4,2,45]
a = [1,1,1,2,2,3]
a.slice!(0) # remove first index
a.slice!(-1) # remove last index
# a = [1,1,2,2] as desired
For speed, I would do the following, which requires only one pass through each of the two arrays. This method preserves order. I will first present code that does not mutate the original array, then show how it can be easily modified to mutate.
arr = [1,1,1,2,2,3,1]
removals = [1,3,1]
h = removals.group_by(&:itself).transform_values(&:size)
#=> {1=>2, 3=>1}
arr.each_with_object([]) { |n,a|
h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n }
#=> [1, 2, 2, 1]
arr
#=> [1, 1, 1, 2, 2, 3, 1]
To mutate arr write:
h = removals.group_by(&:itself).transform_values(&:count)
arr.replace(arr.each_with_object([]) { |n,a|
h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n })
#=> [1, 2, 2, 1]
arr
#=> [1, 2, 2, 1]
This uses the 21st century method Hash#transform_values (new in MRI v2.4), but one could instead write:
h = Hash[removals.group_by(&:itself).map { |k,v| [k,v.size] }]
or
h = removals.each_with_object(Hash.new(0)) { | n,h| h[n] += 1 }