tuple inside another tuple in OCAML - tuples

My question is in the title, here is an example :
(int * string * string * int * (string * string * int) list)
Can i do something like that ? I tryed but it didn't work, i was wondering if there was a way to do that...

Simply :
type t = int * string * string * int * (string * string * int) list;;

Pierre G. explained how to define the type. If you wanted to know how to create such a tuple, you can do it without first defining the type. Just construct a tuple with the data you want. For example:
(1, "two", "three", 4, [("five", "six", 7); ("eight", "nine", 10)]);;
returns
int * string * string * int * (string * string * int) list =
(1, "two", "three", 4, [("five", "six", 7); ("eight", "nine", 10)])

Related

list in SML Language

I'm new to SML and I'm trying to run some code from github in SML/NJ. I'm currently trying to call the function
fun dates_in_month(xs : (int * int * int) list, n : int) =
if null xs then
[]
else if #2 (hd xs) = n then
(hd xs)::dates_in_month(tl xs, n)
else
dates_in_month(tl xs, n)
like so
dates_in_month(3::2::1::nil, 5)
but I get the following error message on SML/NJ 110.97
stdIn:8.1-8.31 Error: operator and operand do not agree [overload - bad instantiation]
operator domain: (int * int * int) list * int
operand: 'Z[INT] list * 'Y[INT]
in expression:
dates_in_month (3 :: 2 :: <exp> :: <exp>, 5)
This issue arises because you're currently trying to call a function of type (int * int * int) list * int -> (int * int * int) list with a parameter of type int list * int. That is to say, the first element of your tuple is of the incorrect type.
You instead want a list of 3-tuples of int. You could construct one like so:
(1, 2, 3) :: (4, 5, 6) :: nil
or a bit briefer as
[(1, 2, 3), (4, 5, 6)]
Note that here the elements of the list are 3-tuples of int as opposed to just ints like you had previously.
The type (int * int * int) list refers to something that looks like:
[(1,2,3), (-69,0,69), (10,100,1000)]
What you are currently passing to the function is:
[3,2,1]
This is because the operator :: is used to construct lists, which are DISTINCT from tuples like (1,2,3). (Basically, a variable of type list can be of any length, whereas a tuple is of a fixed length).

Conditional template default values

Let's say I have a function that returns a random number.
//defines the max value's interval
enum class Type {
INCLUSIVE,
EXCLUSIVE
};
template<typename T = int, Type Interval = Type::EXCLUSIVE>
T rand(const T min, const T max);
This currently works as expected, the usage is as follows:
int result = rand(1,6); //returns an int [1, 6)
double result = rand(1.0, 6.0); //returns a double [1.0, 6.0)
int result = rand<int, Type::INCLUSIVE>(1, 6); // returns an int [1, 6]
double result = rand<double, Type::INCLUSIVE>(1.0, 6.0); //returns a double [1.0, 6.0]
I want the Interval to have a default value depending on what T is passed in. For example, if T is an int, the Interval will be EXCLUSIVE. If T is a double (or floating point), Interval will be INCLUSIVE.
I tried using std::conditional like so:
template<typename T = int, typename Type Interval = std::conditional<std::is_integral<T>::value, Type::EXCLUSIVE, Type::INCLUSIVE>::type>
T RandomNumber(const T min, const T max);
Where the expected behavior is:
int result = rand(1,6); //returns an int [1, 6)
double result = rand(1.0, 6.0); //returns a double [1.0, 6.0]
//with the possibility of still overriding the default behavior e.g.
int result = rand<int, Type::INCLUSIVE>(1,6); //returns an int [1, 6]
I can't get it to work because I get C2783 could not deduce template argument for "Interval".
Is there another way of doing this or am I doing it incorrectly?

Weird result difference in calculation with same numbers

I have the following code (m_threshold (in interval [0..1]) and binSize (=1000) are constants):
std::vector<std::vector<ResidualEntry>> *bins = new std::vector<std::vector<ResidualEntry>>;
... //filling vector
int n = bins->size(); //is 27779
double a = -(2 * (n * binSize - m_threshold * pointCount)) / ((n * n + n) * binSize);
double a2 = -(2 * (bins->size() * binSize - m_threshold * pointCount)) / ((bins->size() * bins->size() + bins->size()) * binSize);
a and a2 return completely different numbers. a is about 0.02 and a2 is -3.6e-5 which is the correct one
Why does this happen?
Thanks to #SirDarius: vector::size() returns a value of type size_type which should normally be an unsigned value, while int is a signed value, making the two lines completely different. After using size_t for initializing n, it all works now.

How to use pow() in Swift 3 and get an Int

I have the following code:
let lootBase = Int(pow((Decimal(level + 1)), 3) * 2)
let lootMod = Int(pow(Decimal(level), 2) * 2)
value = Int(arc4random_uniform(UInt32(lootBase)) + lootMod)
I need value to be an Int. The error I get when I try to surround the pow calculation for Int() is:
Cannot invoke initializer for type int with an argument list of type Decimal
How do I use the pow function with Int in Swift 3?
Int does not have an initializer taking Decimal, so you cannot convert Decimal to Int directly with an initializer syntax like Int(...).
You can use pow(Decimal, Int) like this:
let lootBase = Int(pow((Decimal(level + 1)), 3) * 2 as NSDecimalNumber)
let lootMod = Int(pow(Decimal(level), 2) * 2 as NSDecimalNumber)
let value = Int(arc4random_uniform(UInt32(lootBase))) + lootMod
Or else, you can use pow(Double, Double) like this:
let lootBase = Int(pow((Double(level + 1)), 3) * 2)
let lootMod = Int(pow(Double(level), 2) * 2)
let value = Int(arc4random_uniform(UInt32(lootBase))) + lootMod
But, if you only calculate an integer value's power to 2 or 3, both pow(Decimal, Int) and pow(Double, Double) are far from efficient.
You can declared a simple functions like squared or cubed like this:
func squared(_ val: Int) -> Int {return val * val}
func cubed(_ val: Int) -> Int {return val * val * val}
and use them instead of pow(..., 2) or pow(..., 3):
let lootBase = cubed(level + 1) * 2
let lootMod = squared(level) * 2
let value = Int(arc4random_uniform(UInt32(lootBase))) + lootMod
(Assuming level is an Int.)
Int init() method with no parameter is deprecated for Decimal conversion and should be replaced with Int.init(truncating number: NSNumber) like this
let lootMod = Int(truncating: pow(Decimal(level), 2) * 2 as NSDecimalNumber)
Or
let lootMod = Int(truncating: NSDecimalNumber(decimal: pow(Decimal(level), 2) * 2))
Use decimal for both parameters of pow function.
Maybe the second argument of pow that you are providing is treated as Int instead of Decimal.
Try something like this:
let lootMod = Int(pow(Decimal(level), Decimal(2)) * 2)
A little late for an answer, however:
If level is an Int you could cast it to Float and Use powf() instead of pow() :
let lootBase = Int(powf(Float(level) + 1, 3)) * 2
let lootMod = Int(powf(Float(level), 2)) * 2
If you use UInt32 for addition you should cast all variables to UInt32 before you cast the result to Int:
let value = Int(arc4random_uniform(UInt32(lootBase)) + UInt32(lootMod))
PS: I´m not an expert so check yourself if that works as you expect

Minimization of (z-xi)^2

If I want to find a median (it is equivalent to minimize a function |z - xi|), I can use the following code snippet:
std::vector<int> v{5, 6, 4, 3, 2, 6, 7, 9, 3};
std::nth_element(v.begin(), v.begin() + v.size()/2, v.end());
std::cout << "The median is " << v[v.size()/2] << '\n';
Is there something like this, to find "median" for minimization of (z-xi)^2? That is, I want to find an element of the array in which the sum of these functions will be minimal.
If you want to find the nth_element() according to a predicate comparing (z - xi) ^ 2 you could just add the corresponding logic to the binary predicate you can optionally pass to nth_element():
auto trans = [=](int xi){ return (z - xi) * (z - xi); };
std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end(),
[&](int v0, int v1) { return trans(v0) < trans(v1); });
From the question it isn't clearly whether z or xi is the changing variable. From the looks of it I assumed xi is meant to be xi. If z is changing, just rename the argument in the lambda trans (which I just also gave a = in the capture...).
Your question works on at least two different levels: You're asking how to implement a certain algorithm idiomatically in C++11, and at the same time you're asking for an efficient algorithm for computing the mean of a list of integers.
You correctly observe that to compute the median, all we have to do is run the QuickSelect algorithm with k set equal to n/2. In the C++ standard library, QuickSelect is spelled std::nth_element:
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
const int k = std::size(v) / 2;
std::nth_element(std::begin(v), &v[k], std::end(v)); // mutate in-place
int median = v[v.size()/2]; // now the k'th element is
(For std::size, see proposal N4280, coming soon to a C++17 near you! Until then, use your favorite NELEM macro, or go back to using heap-allocated vector.)
This QuickSelect implementation doesn't really have anything to do with "finding array element xk such that ∑i |xi − xk| is minimized." I mean, it's mathematically equivalent, yes, but there's nothing in the code that corresponds to summing or subtracting integers.
The naïve algorithm to "find array element xk such that ∑i |xi − xk| is minimized" is simply
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
auto sum_of_differences = [v](int xk) {
int result = 0;
for (auto&& xi : v) {
result += std::abs(xi - xk);
}
return result;
};
int median =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return sum_of_differences(xa) < sum_of_differences(xb);
});
This is a horribly inefficient algorithm, given that QuickSelect does the same job.
However, it's trivial to extend this code to work with any mathematical function you want to "minimize the sum of". Here's the same skeleton of code, but with the function "squared difference" instead of "difference":
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
auto sum_of_squared_differences = [v](int xk) {
int result = 0;
for (auto&& xi : v) {
result += (xi - xk) * (xi - xk);
}
return result;
};
int closest_element_to_the_mean =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return sum_of_squared_differences(xa) < sum_of_squared_differences(xb);
});
In this case we can also find an improved algorithm; namely, compute the mean up front and only afterward scan the array looking for the element that's closest to that mean:
int v[] = { 5, 6, 4, 3, 2, 6, 7, 9, 3 };
double actual_mean = std::accumulate(std::begin(v), std::end(v), 0.0) / std::size(v);
auto distance_to_actual_mean = [=](int xk) {
return std::abs(xk - actual_mean);
};
int closest_element_to_the_mean =
std::min_element(std::begin(v), std::end(v), [](int xa, int xb) {
return distance_to_actual_mean(xa) < distance_to_actual_mean(xb);
});
(P.S. – remember that none of the above code snippets should be used in practice, unless you're absolutely sure you don't need to care about integer overflow, floating-point rounding error, and a host of other mathy issues.)
Given an array x1, x2, …, xn of integers, the real number z that minimizes ∑i&in;{1,2,…,n} (z - xi)2 is the mean z* = (1/n) ∑i&in;{1,2,…,n} xi. You want to call std::min_element with a comparator that treats xi as less than xj if and only if |n xi - n z*| < |n xj - n z*| (we use n z* = ∑i&in;{1,2,…,n} xi to avoid floating-point arithmetic; there are ways to reduce the extra precision required).