I want to write a function that is modify every elements inside a matrix.
But I have some problem when compiling.
Warning 10: this expression should have type unit.
I think because all function in ocaml need to return to a value or unit, so if I implement two tasks inside one function, it is not acceptable.
Please help me to fix it.
let nomalize_matrix d a x =
for i = 1 to d do
for j = 1 to d do
let n = i*j in
x.(i)(j) = sprintf "%s_%d" a n
done
done;
x;;
In an expression the = operator in OCaml is a comparison operator that tests for equality. To assign to an array, use the <- operator.
The compiler is complaining because your expression has type bool (i.e., the result of the comparison). The expression in a for should have type unit since its return value is ignored. And indeed, the <- operator returns (), the unit value.
To access an element of a two-dimensional array, the syntax looks like: x.(i).(j). Note the extra dot, not present in your code.
There is no problem in general with doing two things in a function. You can separate two expressions with ; if the first has type unit. The result is the value of the second expression. Your code is OK in this respect.
Just be careful to do not use the operator "=" when you set one item from an array and use the operator "<-" instead so in your code, you have this :
let nomalize_matrix d a x =
for i = 1 to d do
for j = 1 to d do
let n = i*j in
x.(i)(j) <- sprintf "%s_%d" a n
done
done;
x;;
Related
Suppose we want to write a code that prints all ways of selecting n out of m options.
I think, the programming language does not matter, but if I should state it, Python.
I put the assignments in a vector A. Do I better define A as a global variable or pass it to the function each time? Why?
def choose(ind, n):
if n == 0:
print(A)
return
elif len(A)<= ind:
return
else:
A[ind] = 1
choose(ind + 1, n - 1)
A[ind] = 0
choose(ind + 1, n)
Always prefer passing over mutating globals whenever feasible.
Say you have the following functions:
def some_fun1 (n):
return n + 1;
m = 1;
def some_fun2 ():
return m + 1
With the first function, you can load up your REPL and throw data at it just by passing it as an argument. Your testing of that pure function has 0 effect on the rest of the program, which makes testing significantly easier.
With the second function, any time you need to test it, you must manually set all the globals the function relies on, which could potentially affect the operation of other functions if they rely on the same globals. This makes testing harder, and for that reason, among others, mutating globals should be avoided.
I want to go through a matrix and check if any block of it is the same as a predefined unit. Here is my code. 'sd5' is the 2 by 2 predefined unit.
ALLOCATE (fList((n-1)**2,3))
fList = 0
p = 1
DO i = 1, n-1, 1
DO j = 1, n-1, 1
IF (TEST(i:i+1, j:j+1) == sd5) THEN
fList(p,1:3) = (i, j+1, 101) ! 101 should be replaced by submatrix number
END IF
p = p+1
END DO
END DO
The problem seems to be in the IF statement as four logical statements are returned in TEST(i:i+1, j:j+1) == sd5. I get this error:
Error: IF clause at (1) requires a scalar LOGICAL expression
I get another error:
fList(p,1:3) = (i, j+1, 101) ! 101 should be replaced by sub matrix number
1
Error: Expected PARAMETER symbol in complex constant at (1)
I do not understand this error, as all variables are integer which I defined.
First, if statements require scalar clauses.
(TEST(i:i+1, j:j+1) == sd5)
results in a 2x2 matrix containing .true. or .false.. Since you want to check all entries, the statement should read
IF ( all( TEST(i:i+1, j:j+1) == sd5) ) THEN
[ You could also use any if only one matching entry is sufficient. ]
The second statement is a little tricky, since you do not state what you want to achieve. As it is, it is not what you would expect. My guess is that you are trying to store a vector of length three, and the assignment should read
fList(p,1:3) = (/ i, j+1, 101 /)
or
fList(p,1:3) = [ i, j+1, 101 ]
The syntax you provided is in fact used to specify complex constants:
( Real, Imag )
In this form, Real and Imag need to be constants or literals themselves, cf. the Fortran 2008 Standard, R417.
I wrote the function as:
function f = factorial(x)
f = prod(1:x);
f =factorial(5);
end
But when I tried running it, it says input argument not defined.
What's wrong with this?
You have defined a function which recurses endlessly.
f = factorial(5);
in the third line will call your function again, which will then again call your function once it reaches the third line, which then again will call your function... so it will never get done.
When implementing a recursive solution you need to provide a base case. Here's an example for calculating factorials.
function f = factorial(x)
if x == 0 % this is the base case
f = 1;
else
f = x*factorial(x-1); % this is the recursive case
end
end
example:
>> factorial(5)
ans =
120
As for your
input argument not defined
problem, you need to tell us what you actually used as an input argument. For the above example, any* integer x>=0 should work.
*as long as f has enough bytes to hold the result.
Using pseudo-code, if I have an array of integer, how can I make a single big integer that represents the same array in bits?
Example of input (using bits):
[10101, 10001, 00010, 01100]
The integer should be:
10101100010001001100
or
01100000101000110101
number = 0
for each element e
number *= 1 + maximumRepresentableNumber
number += e
For your example, maximumRepresentableNumber will be 11111, as that is the maximum number we can represent using the allowed number of bits (5). Adding 1 to that gives us 100000, and, if we multiply by that, it will be equivalent to a bit-shift by 5 to the left.
This would work for decimal representation as well, i.e. [123, 55, 29] will return 123055029. In this case maximumRepresentableNumber will be 999, so we'd just be multiplying by 1000.
What you are looking for is well known in functional programming land as fold or reduce. The basic idea is, that in a list
a,b,c,d, ..., x
we replace the commas with an operation we want (the operation beig symbolaized by $ here):
a $ (b $ (c $ (d $ ...(x $ Z))) // right fold
and the empty list with some default value Z
A bit different is the left fold, where we start out with Z:
((((Z $ a) $ b) $ c ).... $ x)))
The genral imperative algorithm for left fold would be:
result = Z
for each e in list do result = result $ e
Now, the only problem left is to identify $ and Z, that is the function we want to apply subsequently to all list elements to reach the goal and the starting value. In your case, what you want is either:
append the stringified element to the result string. Z is the empty string.
or: add the element to the result so far multiplied with 2^5. Z would be 0.
In ruby:
answer = 0
[0b10101, 0b10001, 0b00010, 0b01100].each do |x|
answer <<= 5
answer |= x
end
puts answer.to_s(2) # 10101100010001001100
In Python this would be:
a = [0b10101, 0b10001, 0b00010, 0b01100]
b = 0
for elem in a:
b <<= elem.bit_length()
b += elem
print(bin(b))
I have a forvalues loop:
forvalues x = 1(1)50 {
/* Code goes here */
}
Instead of 50, ideally, I would like that value to come as follows. I have a variable name. Let length = length(name). Whatever the largest value is for length, I would like that to be in place of the 50. I could not figure how to write a forvalues loop in which the end point was not directly stated numerically.
I am thinking that I could deduce the maximum length of the variable as follows:
gen id = 1
gen length = length(name)
by id, sort: egen maxlength = max(length)
From there though I do not know how to store this value into the for loop.
Alternatively, would this be better coded by a while loop?
Something like:
gen x = 1
while (x <= maxlength) {
/* Same Code Here */
replace x = x + 1
}
Based on the documentation I've read, it is possible to use macros but with the caveat that changing the end of the range within the forvalues loop has no effect on the number of times the loop will occur. For instance, if length(name) is 50 when the forvalues loop starts, and you change the length of name within the loop, it will still only loop 50 times.
Technically, you'd be better off using a while loop since forvalues was intended to be used when the end of the range is a literal value. You can use a forvalues loop, but you should use a while loop.
Here's my source to back this up:
http://www.stata.com/manuals13/pforvalues.pdf
Specifically:
Technical note
It is not legal syntax to type
. scalar x = 3
. forvalues i = 1(1)x' {
2. local x =x' + 1
3. display `i'
4. }
forvalues requires literal numbers. Using macros, as shown in the following technical note, is
allowed.
And:
Using macros, as shown in the following technical note, is
allowed.
Technical note
The values of the loop bounds are determined once and for all the first time the loop is executed.
Changing the loop bounds will have no effect. For instance,
will not create an infinite loop. With `n' originally equal to 3, the loop will be performed three
times.
local n 3
forvalues i = 1(1)`n' {
local n = `n' + 1
display `i'
}
Output:
1
2
3
Here is the trick with Stata which I think may work for you. I am using the data auto from Stata datasets.
sysuse auto
Suppose the variable name here be price. Now you want the length of variable price.
sum price
gen length=r(N)
To see what is r(N) type return list after running the sum price.
In your loop it goes like follows: (Updated as per #Nick)
forvalues x = 1/`r(N)'{
/* Code goes here */
}
OR:
local length=r(N)
forvalue i=1/`length'{
dis "`i'"
}
Note: It is not clear why you want for loop.So my answer is restricted to what you only asked for.
#Metrics' first code won't quite work. Here is a better way, cutting out what I call the middle macro.
Start with something more like
. su price, meanonly
. forval j = 1/`r(N)' {
An equivalent approach to the one proposed by #Nick and #Metrics is the following:
sysuse auto, clear
count if !missing(price)
forvalues x = 1 / `r(N)' {
/* Code goes here */
}