Creating nested arrays in swift - arrays

I'm trying to create nested arrays in Swift of data that's input in the following format:
(+ 5 (- 1 (+ 34 1)))
So the nested array would look like:
[+, 5, [-, 1, [+, 34, 1]]]
with arr[0] always being the operation (+,-,*, or /)
I'm very new to swift and don't really know where to start, so I'd really appreciate the help.

You can put integers, strings, and even functions in the same array by using an enumeration and its associated values. The example does not lend itself to an array but simply a recursive nesting of numbers and computations.
enum Input {
case Operator((Int, Int) -> Int)
case Number(Int)
}
Edit: Per Rob's suggestion.
enum Input {
case Operator((Int, Int) -> Int)
case Number(Int)
indirect case Computation(operator: Input, left: Input, right: Input)
}
This shows how to declare a recursive enumeration. I wish there was a way to limit the operator parameter to Input.Operator and parameters left and right to Input types not .Operator.

you could use array with type of AnyObject as below example.
let arr: [AnyObject] = ["+", 5, ["-", 1, ["/", 34, 1]]]
So in order to get operand you can get at index 0. Let say you want operand division "/" as sample above you can go at this index
arr[2][2][0]

As Price Ringo suggests, a recursive enum is definitely the right tool here. I would build it along these lines:
enum Operator {
case Add
case Subtract
}
enum Expression {
indirect case Operation(Operator, Expression, Expression)
case Value(Int)
}
let expression = Expression.Operation(.Add,
.Value(5),
.Operation(.Subtract,
.Value(1),
.Operation(.Add, .Value(34), .Value(1))))
If you wanted to, you could do it Price's way with functions, and that's probably pretty clever, but I suspect would actually be more of a headache to parse. But if you wanted to, it'd look like this:
enum Expression {
indirect case Operation((Int, Int) -> Int, Expression, Expression)
case Value(Int)
}
let expression = Expression.Operation(+,
.Value(5),
.Operation(-,
.Value(1),
.Operation(+, .Value(34), .Value(1))))
Alternately, you could create an Operator type rather than passing in functions. That's how I'd probably recommend going unless you really want to be able tow

I think you can't build the arrays with different types.. I mean you want to build an Array with Integers and the operators should be Strings... but you can't have both in an array.
check this link, it might be helpful http://totallyswift.com/nested-collections/

Your example looks like a classic Lisp expression. Reflecting that, have you considered the possibility that arrays are a force fit, and you might have an easier time of it with lists as the underlying representation? A list data type would be trivial to implement.

Related

Custom searchsortedfirst method

I'm kinda new in Julia lang, so I'm still struggling with reading Julia documentation. Here is a piece of it and I am looking for explanation specifically the bolded part.
Base.Sort.searchsortedfirst — Function.
searchsortedfirst(a, x, [by=,] [lt=,]
[rev=false])
Returns the index of the first value in a greater than or equal to x,
according to the specified order. Returns length(a)+1 if x is greater
than all values in a. a is assumed to be sorted.
Website
My array looks like this:
A = Vector{Record}()
where
type Record
y::Int64
value::Float64
end
Now here is my problem. I would like to call above-mentioned method on my array and obtain Record where given x equals y in this Record (Record.y == x). Guess I have to write 'by' transfrom or 'lt' comparator? or both?
Any help would be appraciated :)
#crstnbr has provided a perfectly good answer for the case of one-off uses of searchsortedfirst. I thought it worth adding that there is also a more permanent solution. If your type Record exhibits a natural ordering, then just extend Base.isless and Base.isequal to your new type. The following example code shows how this works for some new type you might define:
struct MyType ; x::Float64 ; end #Define some type of my own
yvec = MyType.(sort!(randn(10))) #Build a random vector of my type
yval = MyType(0.0) #Build a value of my type
searchsortedfirst(yvec, yval) #ERROR: this use of searchsortedfirst will throw a MethodError since julia doesn't know how to order MyType
Base.isless(y1::MyType, y2::MyType)::Bool = y1.x < y2.x #Extend (aka overload) isless so it is defined for the new type
Base.isequal(y1::MyType, y2::MyType)::Bool = y1.x == y2.x #Ditto for isequal
searchsortedfirst(yvec, yval) #Now this line works
Some points worth noting:
1) In the step where I overload isless and isequal, I preface the method definition with Base.. This is because the isless and isequal functions are originally defined in Base, where Base refers to the core julia package that is automatically loaded every time you start julia. By prefacing with Base., I ensure that my new methods are added to the current set of methods for these two functions, rather than replacing them. Note, I could also achieve this by omitting Base. but including a line beforehand of import Base: isless, isequal. Personally, I prefer the way I've done it above (for the overly pedantic, you can also do both).
2) I can define isless and isequal however I want. It is my type and my method extensions. So you can choose whatever you think is the natural ordering for your new type.
3) The operators <. <=, ==, >=, >, all actually just call isless and isequal under the hood, so all of these operators will now work with your new type, eg MyType(1.0) > MyType(2.0) returns false.
4) Any julia function that uses the comparative operators above will now work with your new type, as long as the function is defined parametrically (which almost everything in Base is).
You can just define a custom less-than operation and give it to searchsortedfirst via lt keyword argument:
julia> type Record
y::Int64
value::Float64
end
julia> A = Vector{Record}()
0-element Array{Record,1}
julia> push!(A, Record(3,3.0))
1-element Array{Record,1}:
Record(3, 3.0)
julia> push!(A, Record(4,3.0))
2-element Array{Record,1}:
Record(3, 3.0)
Record(4, 3.0)
julia> push!(A, Record(5,3.0))
3-element Array{Record,1}:
Record(3, 3.0)
Record(4, 3.0)
Record(5, 3.0)
julia> searchsortedfirst(A, 4, lt=(r,x)->r.y<x)
2
Here, (r,x)->r.y<x is an anonymous function defining your custom less-than. It takes two arguments (the elements to be compared). The first will be the elements from A, the second is the fixed element to compare to.

MiniZinc join arrays of variables by index

I have a MiniZinc program with 3 arrays of variables of the following form:
array[NbLines] of var Domain: vars1;
array[NbLines, NbRows] of var Domain: vars2;
array[NbLines, NbRows] of var Domain: vars3;
I need to specify my search variable order in the following way, but I did not success to correctly construct my array. There is the MiniZinc like code:
varsOrder = [[vars1[i]] ++ row(vars2, i) ++ row(vars3, i) | i in NbLines]
MiniZinc indicates that arrays are not allowed in array comprehension expressions. How should I do?
Thank you for your help.
As you have noticed, you cannot concatenate arrays like this. What I can think of are two approaches, though the first is not exactly what you want.
1) use array1d(array)
You can flatten matrices (2d arrays) with "array1d" like this:
solve :: int_search(vars1 ++ array1d(vars2) ++ array1d(vars3), first_fail, indomain_min, complete) satisfy;
However, this is not exactly the same as what you write above, but it's way easier than the next approach:
2) Make a master array and insert all the elements in the proper positions.
int: totLen = ...; % the total length of all the arrays
array[1..totLen] of var Domain: all;
You have to do a loop to insert all the elements in the exact position you want in the "all" array. However, I leave this as an exercise. :-)
Then the "all" array can be used in the labeling:
solve :: int_search(all, first_fail, indomain_min, complete) satisfy;

How do I change the data type of a Julia array from "Any" to "Float64"?

Is there a function in Julia that returns a copy of an array in a desired type, i.e., an equivalent of numpys astype function? I have an "Any" type array, and want to convert it to a Float array. I tried:
new_array = Float64(array)
but I get the following error
LoadError: MethodError: `convert` has no method matching
convert(::Type{Float64}, ::Array{Any,2})
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Closest candidates are:
call{T}(::Type{T}, ::Any)
convert(::Type{Float64}, !Matched::Int8)
convert(::Type{Float64}, !Matched::Int16)
...
while loading In[140], in expression starting on line 1
in call at essentials.jl:56
I can just write a function that goes through the array and returns a float value of each element, but I find it a little odd if there's no built-in method to do this.
Use convert. Note the syntax I used for the first array; if you know what you want before the array is created, you can declare the type in front of the square brackets. Any just as easily could've been replaced with Float64 and eliminated the need for the convert function.
julia> a = Any[1.2, 3, 7]
3-element Array{Any,1}:
1.2
3
7
julia> convert(Array{Float64,1}, a)
3-element Array{Float64,1}:
1.2
3.0
7.0
You can also use the broadcast operator .:
a = Any[1.2, 3, 7]
Float64.(a)
You can use:
new_array = Array{Float64}(array)
Daniel and Randy's answers are solid, I'll just add another way here I like because it can make more complicated iterative cases relatively succinct. That being said, it's not as efficient as the other answers, which are more specifically related to conversion / type declaration. But since the syntax can be pretty easily extended to other use case it's worth adding:
a = Array{Any,1}(rand(1000))
f = [float(a[i]) for i = 1:size(a,1)]

Is it possible to define the length of a list in F#?

For example, I define a record as:
type a = {b : float; c: int list}
but I already know that this list must be of a predefined size, let's say 2 and if the list is not 2 it would be a different type or error since it is not defined such a type.
Is it possible to define the size of the list as happens in other languages that you must define the size?
Depending on the application this question can be applied to an array.
Maybe you should use an array instead of a list, since an array has a fixed length:
// create an array of length = 2, initialized with zeros.
let cValues : int[] = Array.create 2 0
cValues.IsFixedSize // returns true
EDIT: As others have suggested, a tuple might also be the way to go. For a pair (a tuple of length two), you can access the values using the fst and snd functions.
For a longer tuple, you can use pattern matching as shown below. If the tuple is too long to make this pattern matching approach practical, then you probably need a structure other than an F# tuple. Of course, one major requirement to consider is whether you need to store values of mixed types. A tuple or a record can store a mix of multiple types, whereas an array or list stores values of a single type.
let fourTuple = (5, 10, 2, 3)
let _,_,third,_ = fourTuple
printfn "%d" third // displays "2"
If an array or a tuple won't meet your requirements, then maybe you should use another record like this:
type ListOfC = {c1 : int; c2 : int}
type a' = {b' : float; c' : ListOfC}
Or you could create a new class that would meet your requirements, starting like the script below. Of course, this would probably not be considered idiomatic functional programming style. It's more like OOP.
type ListOfTwo(firstInt : int, secondInt : int) =
member this.First = firstInt
member this.Second = secondInt
let myListOfTwo = ListOfTwo(4, 5)
myListOfTwo.First
type a = {b : float; c : ListOfTwo }

Concise way to create an array filled within a range in Matlab

I need to create an array filled within a range in Matlab
e.g.
from=2
to=6
increment=1
result
[2,3,4,5,6]
e.g.
from=15
to=25
increment=2
result
[15,17,19,21,23,25]
Obviously I can create a loop to perform this action from scratch but I wondering if there is a coincise and efficent way to do this with built-in matlab commands since seems a very common operation
EDIT
If I use linspace the operation is weird since the spacing between the points is (x2-x1)/(n-1).
This can be handled simply by the : operator in the following notation
array = from:increment:to
Note that the increment defaults to 1 if written with only one colon seperator
array = from:to
Example
array1 = 2:6 %Produces [2,3,4,5,6]
array2 = 15:2:25 %Produces [15,17,19,21,23,25]

Resources