F# beginner using let on multiple dependent names - f#

I hate to ask such a noob question, but I have hunted high and low online--and this is literally my first day.
The following VBA excerpt assigns two variables, where the first variable feeds into the second variable (this code is from www.spreadsheetadvice.com):
If zabs <= 12.7 Then
...
If zabs <= 1.28 Then
Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
Q = a0 - zabs * (a1 - a2 * y / Temp)
Else
Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
Q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
End If
Else ...
I'm trying to replicate it in F#--without using mutables. This works:
let Temp =
if zabs <= 1.28 then
y + a3 - a4 / (y + a5 + a6 / (y + a7))
elif zabs <= 12.7 then
(zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
else
0.0
let Q =
if zabs <= 1.28 then
a0 - zabs * (a1 - a2 * y / Temp)
elif zabs <= 12.7 then
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
else
0.0
But I don't like separating the two related variables--or repeating the If statements. This doesn't work but is as close as I've come:
let Temp, Q =
if zabs <= 1.28 then
y + a3 - a4 / (y + a5 + a6 / (y + a7)),
a0 - zabs * (a1 - a2 * y / Temp)
elif zabs <= 12.7 then
(zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11)))),
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
else
0.0,
0.0
It took me a while to figure out the commas on the 3rd, 6th, and 9th lines (if they are in fact right). But the compiler thinks I am trying to use Temp before it is assigned. I assume, or hope, I'm just missing a simple idiom.

This works:
let Temp, Q =
if zabs <= 1.28 then
let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
let q = a0 - zabs * (a1 - a2 * y / temp)
temp, q
elif zabs <= 12.7 then
let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
temp, q
else
0.0, 0.0

It took me a while to figure out the commas on the 3rd, 6th, and 9th lines (if they are in fact right). But the compiler thinks I am trying to use Temp before it is assigned. I assume, or hope, I'm just missing a simple idiom.
Yes, you are missing the basics of the language, you must put the commas because you declare a tuple so you have to bind a value of type 'a * 'b
I suggest to use pattern matching, one of the more powerful thing of F# (and other functional languages) - https://msdn.microsoft.com/en-us/library/dd547125.aspx
let yourfunc zabs =
match zabs with
| x when x <= 1.28 -> let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
let q = a0 - zabs * (a1 - a2 * y / temp)
temp, q
| x when x <= 12.7 -> let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
temp, q
| _ -> 0.0,0.0

I think I was making a simple mistake: because Temp is temporary and subordinate to Q, then Temp should be declared with a scope local to the declaration of Q, not with equal scope as Q. With that figured out, I think using If and using Match work equally well. But Match is probably more idiomatic (thanks Alessandro). Thusly:
let Q =
match zabs with
| i when i <= 1.28 ->
let Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
a0 - zabs * (a1 - a2 * y / Temp)
| i when i <= 12.7 ->
let Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
| _ ->
0.0
So now I'm bound to want to make two declarations that do need to be of the same scope some time soon and come back to a similar situation again...

Related

Google Sheets - Convert UTF-8 Text to "normal character"

I'm looking for a solution to convert strings formatted in UTF-8? (Avr%C3%ACl) to their normal appearance.
It is a list of Names that should be readable:
Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC
With a list of codes i want to replace them with:
...
Ò c3 92 %c3%92
Ó c3 93 %c3%93
Ô c3 94 %c3%94
Õ c3 95 %c3%95
Ö c3 96 %c3%96
× c3 97 %c3%97
Ø c3 98 %c3%98
Ù c3 99 %c3%99
Ú c3 9a %c3%9a
Û c3 9b %c3%9b
Ü c3 9c %c3%9c
...
I found app-spript snippets, and "hardcoded" =substitute() but since there are not only 5 characters to be searched, i dont want to nest 200+ substitutes inside each other.
Any solutions?
EDIT:
I haven't been clear enough. Sorry for that. I need to "translate" the names in their cells one by one. The keyword was the list for the app-script answer i guess. Actually it is a table of contents where A2 ist the link to the charakter page, B2 the Name i have already extraced from A2 and C2, the server, is also extracted.
A2 Formula:
just a link
B2 Formula:
=trim(regexreplace(trim(REGEXREPLACE(A2;"https://www.wowprogress.com/character/eu";""));"/"&C2&"/";""))
C2 Formula:
=trim(REGEXEXTRACT(trim(REGEXREPLACE(A2;"https://www.wowprogress.com/character/eu";""));"([^/?]+)"))
List of Chars:
! 21 %21
" 22 %22
# 23 %23
$ 24 %24
% 25 %25
& 26 %26
27 %27
( 28 %28
) 29 %29
* 2a %2a
#ERROR! 2b %2b
, 2c %2c
- 2d %2d
. 2e %2e
/ 2f %2f
0 30 %30
1 31 %31
2 32 %32
3 33 %33
4 34 %34
5 35 %35
6 36 %36
7 37 %37
8 38 %38
9 39 %39
: 3a %3a
; 3b %3b
< 3c %3c
#ERROR! 3d %3d
> 3e %3e
? 3f %3f
# 40 %40
A 41 %41
B 42 %42
C 43 %43
D 44 %44
E 45 %45
F 46 %46
G 47 %47
H 48 %48
I 49 %49
J 4a %4a
K 4b %4b
L 4c %4c
M 4d %4d
N 4e %4e
O 4f %4f
P 50 %50
Q 51 %51
R 52 %52
S 53 %53
T 54 %54
U 55 %55
V 56 %56
W 57 %57
X 58 %58
Y 59 %59
Z 5a %5a
[ 5b %5b
\ 5c %5c
] 5d %5d
^ 5e %5e
_ 5f %5f
` 60 %60
a 61 %61
b 62 %62
c 63 %63
d 64 %64
e 65 %65
f 66 %66
g 67 %67
h 68 %68
i 69 %69
j 6a %6a
k 6b %6b
l 6c %6c
m 6d %6d
n 6e %6e
o 6f %6f
p 70 %70
q 71 %71
r 72 %72
s 73 %73
t 74 %74
u 75 %75
v 76 %76
w 77 %77
x 78 %78
y 79 %79
z 7a %7a
{ 7b %7b
| 7c %7c
} 7d %7d
~ 7e %7e
¡ c2 a1 %c2%a1
¢ c2 a2 %c2%a2
£ c2 a3 %c2%a3
¤ c2 a4 %c2%a4
¥ c2 a5 %c2%a5
¦ c2 a6 %c2%a6
§ c2 a7 %c2%a7
¨ c2 a8 %c2%a8
© c2 a9 %c2%a9
ª c2 aa %c2%aa
« c2 ab %c2%ab
¬ c2 ac %c2%ac
­ c2 ad %c2%ad
® c2 ae %c2%ae
¯ c2 af %c2%af
° c2 b0 %c2%b0
± c2 b1 %c2%b1
² c2 b2 %c2%b2
³ c2 b3 %c2%b3
´ c2 b4 %c2%b4
µ c2 b5 %c2%b5
¶ c2 b6 %c2%b6
· c2 b7 %c2%b7
¸ c2 b8 %c2%b8
¹ c2 b9 %c2%b9
º c2 ba %c2%ba
» c2 bb %c2%bb
¼ c2 bc %c2%bc
½ c2 bd %c2%bd
¾ c2 be %c2%be
¿ c2 bf %c2%bf
À c3 80 %c3%80
Á c3 81 %c3%81
 c3 82 %c3%82
à c3 83 %c3%83
Ä c3 84 %c3%84
Å c3 85 %c3%85
Æ c3 86 %c3%86
Ç c3 87 %c3%87
È c3 88 %c3%88
É c3 89 %c3%89
Ê c3 8a %c3%8a
Ë c3 8b %c3%8b
Ì c3 8c %c3%8c
Í c3 8d %c3%8d
Î c3 8e %c3%8e
Ï c3 8f %c3%8f
Ð c3 90 %c3%90
Ñ c3 91 %c3%91
Ò c3 92 %c3%92
Ó c3 93 %c3%93
Ô c3 94 %c3%94
Õ c3 95 %c3%95
Ö c3 96 %c3%96
× c3 97 %c3%97
Ø c3 98 %c3%98
Ù c3 99 %c3%99
Ú c3 9a %c3%9a
Û c3 9b %c3%9b
Ü c3 9c %c3%9c
Ý c3 9d %c3%9d
Þ c3 9e %c3%9e
ß c3 9f %c3%9f
à c3 a0 %c3%a0
á c3 a1 %c3%a1
â c3 a2 %c3%a2
ã c3 a3 %c3%a3
ä c3 a4 %c3%a4
å c3 a5 %c3%a5
æ c3 a6 %c3%a6
ç c3 a7 %c3%a7
è c3 a8 %c3%a8
é c3 a9 %c3%a9
ê c3 aa %c3%aa
ë c3 ab %c3%ab
ì c3 ac %c3%ac
í c3 ad %c3%ad
î c3 ae %c3%ae
ï c3 af %c3%af
ð c3 b0 %c3%b0
ñ c3 b1 %c3%b1
ò c3 b2 %c3%b2
ó c3 b3 %c3%b3
ô c3 b4 %c3%b4
õ c3 b5 %c3%b5
ö c3 b6 %c3%b6
÷ c3 b7 %c3%b7
ø c3 b8 %c3%b8
ù c3 b9 %c3%b9
ú c3 ba %c3%ba
û c3 bb %c3%bb
ü c3 bc %c3%bc
ý c3 bd %c3%bd
þ c3 be %c3%be
ÿ c3 bf %c3%bf
Without any substitute, try
function myFunction(){
var txt = `Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC`
console.log(utf8decode(unescape(txt)))
}
and add this function
function utf8decode(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
var txt = `Shiv%C3%A3z
H%C3%B4nd%C3%AAmon
H%C3%B4nd%C3%AAmon
Rev%C3%A1
%C3%90reamy
F%C3%A5m%C3%A9
Nob%C3%B4
Nosh%C3%AC`
console.log(utf8decode(unescape(txt)))
function utf8decode(utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
based on gitbub
if you change your mind with SUBSTITUTE brute force:
={""; INDEX("=INDEX(IFERROR("&REPT("SUBSTITUTE(", COUNTA(E2:E))&"A:A, "&QUERY("D"&
SEQUENCE(COUNTA(D2:D), 1, ROW(D2))&", "&"E"&
SEQUENCE(COUNTA(D2:D), 1, ROW(D2))&"),",,9^9)&" ))")}
spreadsheet demo

Maxima collecting specific terms in an expression

I have an expression that actually can be expressed in simple form by collecting the specific terms. I have problem in Maxima to substitute or simplify the expression to the known terms.
(%i1) expr:(16*h^2*v_0^2+(38*h*u_0-38*h*u_1)*v_0+25*u_1^2-50*u_0*u_1+25*u_0^2)/3;
2 2 2 2
16 h v_0 + (38 h u_0 - 38 h u_1) v_0 + 25 u_1 - 50 u_0 u_1 + 25 u_0
(%o1) -----------------------------------------------------------------------
3
(%i2) eq1:a1=-h*v_0+2*u_1-2*u_0;
eq2:a2=-2*(h*v_0-u_1+u_0);
(%o2) a1 = (- h v_0) + 2 u_1 - 2 u_0
(%i3)
(%o3) a2 = - 2 (h v_0 - u_1 + u_0)
(%i4) subst([eq1,eq2],expr);
2 2 2 2
16 h v_0 + (38 h u_0 - 38 h u_1) v_0 + 25 u_1 - 50 u_0 u_1 + 25 u_0
(%o4) -----------------------------------------------------------------------
3
What I want is something like this
expr=c1*(a1)^q1 + c2*(a2)^q2
where c1,c2,q1,q2 are the constant that would generated by simplifying expr using known term a1,a2. How to do that? Is there any specific syntax?

how to run formula for a range (like a loop) and sum the results?

In google sheets, I am using a formula like this:
=SUM(
VLOOKUP(D2,I2:J8,2,FALSE) * E2,
VLOOKUP(D3,I2:J8,2,FALSE) * E3,
VLOOKUP(D4,I2:J8,2,FALSE) * E4,
VLOOKUP(D5,I2:J8,2,FALSE) * E5,
VLOOKUP(D6,I2:J8,2,FALSE) * E6
)
How to write it as a range? like
=SUM(VLOOKUP(x,I2:J8,2,FALSE) * y)
x is D2 to D6
y is E2 to E6
Try this:
=arrayformula(SUM(VLOOKUP(D2:D6,I2:J8,2,FALSE)*E2:E6))

Substitute variable in Maxima

newbie Maxima question
I have a transfer function in Maxima
E1 : y = K_i*s/(s^2 + w^2);
I'd like to have the closed-form of the equation affter applying the bilinear transform
E2 : s = (2/Ts*(z-1)/(z+1));
I would like to get the transfer function for z, by substituing s by equation E2. How should I proceed?
Regards
Note that subst can apply one or more substitutions stated as equations. In this case, try subst(E2, E1).
That will probably create a messy result -- you can simplify it somewhat by applying ratsimp to the result.
Here's what I get from that.
(%i2) E1 : y = K_i*s/(s^2 + w^2);
K_i s
(%o2) y = -------
2 2
w + s
(%i3) E2 : s = (2/Ts*(z-1)/(z+1));
2 (z - 1)
(%o3) s = ----------
Ts (z + 1)
(%i4) subst (E2, E1);
2 K_i (z - 1)
(%o4) y = ------------------------------
2
4 (z - 1) 2
Ts (z + 1) (------------ + w )
2 2
Ts (z + 1)
(%i5) ratsimp (%);
2
2 K_i Ts z - 2 K_i Ts
(%o5) y = -----------------------------------------------
2 2 2 2 2 2 2
(Ts w + 4) z + (2 Ts w - 8) z + Ts w + 4

How to pass same parameters to multiple functions?

I have a bunch of functions that I want to compute with the same inputs. Is there a better way to see the outputs than the way I chose below?
open MathNet.Numerics.Distributions
// The functions
let EuVanillaPut S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1)
let BSMdelta S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.CDF(0.0,1.0,d1)
let BSMgamma S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.PDF(0.0,1.0,d1) / (S0 * sigma * sqrt(T))
let BSMvega S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
Normal.PDF(0.0,1.0,d1) * S0 * sqrt(T)
let BSMthetacall S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
-S0 * Normal.PDF(0.0,1.0,d1) * sigma / (2.0*sqrt(T)) - r*K*exp(-r*T)*Normal.CDF(0.0,1.0,d2)
let BSMthetaput S0 K T r sigma =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
-S0 * Normal.PDF(0.0,1.0,d1) * sigma / (2.0*sqrt(T)) + r*K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2)
// Calling them all at once on the same inputs
// So ugly! Is there a better way?
(30.0, 25.0, 5.0, 0.02, 0.05)
|> fun (S0, K, T, r, sigma) -> [EuVanillaPut S0 K T r sigma;
BSMdelta S0 K T r sigma;
BSMgamma S0 K T r sigma;
BSMvega S0 K T r sigma;
BSMthetacall S0 K T r sigma;
BSMthetaput S0 K T r sigma]
I'm pretty new to F#, should I make a type for this? Should I be using a different data structure as an input for the functions? Any and all pointers are much appreciated.
As suggested in the comments, one option is to create a list of functions and then use List.map to iterate over all the functions and call them:
let results =
[ EuVanillaPut; BSMdelta; BSMgamma ]
|> List.map (fun f -> f 30.0 25.0 5.0 0.02 0.05)
I suppose you'd then also want to extract the individual results - to do that, you can use pattern matching (but you will get a warning, because the compiler cannot know that the number of elements in the list is correct):
let [euVanillaPut; bsmdelta; bsmgamma] = results
To avoid the warning, you'd have to write:
match results with
| [euVanillaPut; bsmdelta; bsmgamma] -> // all good
| _ -> failwith "This should not happen..."
Alternatively, you could change the function definition to use tuple (or a record):
let EuVanillaPut (S0, K, T, r, sigma) =
let d1 = (log(S0/K) + (r + sigma ** 2.0 / 2.0) * T)/(sqrt(T)*sigma)
let d2 = d1 - sqrt(T)*sigma
K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1)
Then you can define a single tuple to hold the parameters and use it as an argument to multiple functions:
let ps = (30.0, 25.0, 5.0, 0.02, 0.05)
let euVanillaPut = EuVanillaPut ps
let bsmdelta = BSMdelta ps
let bsmgamma = BSMgamma ps
The first approach is a clever trick, but if you are doing this often, then extracting the individual results from the list will be a bit ugly. The second approach is simpler and makes more sense if you have a lot of functions with the same group of parameters.

Resources