Google Sheet If-statement formula - google-sheets

I have a formula calculating a number :
F = SUMIFS(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5)
What I try to do then is to print either the result :
if F > 0, or "-" if F = 0
So I try with the IF function :
=IF(F=0;"-";?)
I don't know what to use to print the correct result when it is false. Anyone know how I could do it?

Unfortunately, you cannot set a variable in a spreadsheet formula; that is, you cannot actually set the name F to your SUM expression there. You can either write:
=IF(SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5)=0,"-",SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5))
Or you could store SUM(Besoins!$D$2:$D$999;Besoins!$C$2:$C$999;C$1;Besoins!$B$2:$B$999;$B5) in one cell (for the sake of argument, cell A1) and in another cell, write:
=IF(A1=0,"-",A1)

Related

s it possible to use =substitute on x in a linear equation and solve it?

everyone. I'm trying to do an iterative equation solver, where I put an equation then each iteration substitutes the X for a value then solves it. I'm having a hard time since the iterated function is considered a string. Any help is appreciated, thank you. The equation needs to be dynamic and be solved via iterations.
I tried calling the =substitute cell and end up having invalid data, since it reads as string.
try:
=BYROW(A9:A24, LAMBDA(ii, INDEX(QUERY(,
"select "&REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(B2, "\^\d+", REPT("*x",
REGEXEXTRACT(B2, "\^(\d+)")-1)), "\(", "*("), "x", ii&"")), 2)))
logic:
caret ^ is not supported by QUERY so we first transform ^2 into an alternative. we know x^2 is equal to x*x so we extract that 2 and subtract 1 and REPT *x one time
next, we need to add multiplication as ()() needs to become ()*() same as 50x to 50*x
then we substitute x with value and evaluate the string with QUERY's SQL ## logic:
basically, we transform your:
-50(x)-1/2(-9.81)(x^2)+35
into:
-50*(0)-1/2*(-9.81)*(0*0)+35
-50*(1)-1/2*(-9.81)*(1*1)+35
-50*(2)-1/2*(-9.81)*(2*2)+35
etc.
UPDATE:
x^n where n is <1 are unachievable with REPT method and QUERY does not support roots so we can use a script to convert a text string into the formula
poor script example:
function onEdit(){
var sheet = SpreadsheetApp.getActiveSheet();
var source1= sheet.getRange('F7');
var source2= sheet.getRange('F8');
var formula1 = source1.getValue();
var formula2 = source2.getValue();
var target1 = sheet.getRange('B7');
var target2 = sheet.getRange('B8');
target1.setFormula(formula1);
target2.setFormula(formula2);
}
where F7 contains:
=BYROW(A7:A23, LAMBDA(i, "POW("&INDEX(QUERY(, "select "&REGEXREPLACE(
SUBSTITUTE(REGEXEXTRACT(B3, "(.+)\^"), ")(", ")*("), "x", i&"")), 2)&","&
REGEXEXTRACT(B3, "\^\((.+)\)")&")"))

Obtaining numerical values from the mnewton function of the Maxima program

I use Maxima for calculations. I solve a system of nonlinear equations using Newton's method (mnewton()). I get the solution in the form of a list:
[[φ2=5.921818183272879,s=5.155870949147037]]
How to get the numerical value of the first (φ2) and second (s) unknown. If I substitute:
x: roz1[1][2]$
I get that x is equal to: s=5.155870949147037
What to do to make x equal to a numerical value only: 5.155870949147037
(without s=).
My code:
Maxima code
I have two ideas. (1) You can call rhs to return the right-hand side of an equation (likewise lhs for the left-hand side). E.g. rhs(s = 123) returns 123.
(2) You can call assoc to find the value associated with s (or any variable) in the mnewton results. E.g. assoc('s, [a = 1, b = 2, s = 3, u = 5]) returns 3.
I like (2) better since it is not necessary to know where in the list is the one that you're interested in.

This expression was expected to have type bool but here has type unit error

getting an error when I try to run this line of code and I can't figure out why
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else true
As Tyler Hartwig says a for loop cannot return a value except unit.
On the other hand, inside a list comprehension or a seq Computation Expression you can use for to yield the values and then test if the one you are looking for exists:
let validCol column value : bool =
seq { for i in 0..8 do yield sudokuBoard.[i,column] }
|> Seq.exists value
|> not
In F#, the last call made is what is returned, you have explicitly declared you are returning a bool.
The for loop is unable to return or aggregate multiple values, bun instead, returns unit.
let validCol column value : bool =
for i in 0..8 do
if sudokuBoard.[i,column] = value then
false
else
true
Here, you'll need to figure out how to aggregate all the bool to get your final result. I'm not quite sure what this is supposed to return, or I'd give an example.
It looks like you are looking for a short-cut out of the loop like in C# you can use continue, break or return to exit a loop.
In F# the way to accomplish that with performance is to use tail-recursion. You could achieve it with while loops but that requires mutable variables which tail-recursion doesn't need (although we sometimes uses it).
A tail-recursive function is one that calls itself at the very end and doesn't look at the result:
So this is tail-recursive
let rec loop acc i = if i > 0 then loop (acc + i) (i - 1) else acc
Where this isn't
let rec loop fib i = if i < 1 then 1 else fib (i - 1) + fib (i - 2)
If F# compiler determines a function is tail-recursive the compiler applies tail-recursion optimization (TCO) on the function, basically it unrolls it into an efficient for loop that looks a lot like the loop would like in C#.
So here is one way to write validCol using tail-recursion:
let validCol column value : bool =
// loops is tail-recursive
let rec loop column value i =
if i < 9 then
if sudokuBoard.[i,column] = value then
false // The value already exists in the column, not valid
else
loop column value (i + 1) // Check next row.
else
true // Reach the end, the value is valid
loop column value 0
Unfortunately; F# compiler doesn't have an attribute to force TCO (like Scala or kotlin does) and therefore if you make a slight mistake you might end up with a function that isn't TCO. I think I saw GitHub issue about adding such an attribute.
PS. seq comprehensions are nice in many cases but for a sudoku solver I assume you are looking for something that is as fast as possible. seq comprehensions (and LINQ) I think adds too much overhead for a sudoku solver whereas tail-recursion is about as quick as you can get in F#.
PS. In .NET 2D arrays are slower than 1D arrays, just FYI. Unsure if it has improved with dotnet core.

APL return value of a function

I want to know how to return a value after my function finishes running.
I have, for example:
FUNCTION X
? X ⍴ 10
//This means, generate X random numbers (X is the function's argument) within the range 1-10.
I just want to know how I can return the value of the function, and for example, pass it to another function.
Thank you for your help!
This is done in the Function header (code line 0).
It has the following form:
returnValue ← leftArgument functionName rightArgument ; localized_variables
So, whenever your function terminates, the value of the variable returnValue will be returned.
Alternately, if your APL system supports it, you can use direct definition (dfns, lambdas). This should work in Dyalog, GNU, NARS2000, and NGN APL.
Try
{?⍵⍴10} 42
⍵ is the function's argument (X in your example)
The return value is the result of the expression and does not have to be explicitly stated.
You can also do
function←{?⍵⍴10}
then
function 42

f# deedle filter data frame based on a list

I wanted to filter a Deedle dataframe based on a list of values how would I go about doing this?
I had an idea to use the following code below:
let d= df1|>filterRowValues(fun row -> row.GetAs<float>("ts") = timex)
However the issue with this is that it is only based on one variable, I then thought of combining this with a for loop and an append function:
for i in 0.. recd.length -1 do
df2.Append(df1|>filterRowValues(fun row -> row.GetAs<float>("ts") = recd.[i]))
This does not work either however and there must be a better way of doing this without using a for loop. In R I could for instance using an %in%.
You can use the F# set type to create a set of the values that you are interested. In the filtering, you can then check whether the set contains the actual value for the row.
For example, say that you have recd of type seq<float>. Then you should be able to write:
let recdSet = set recd
let d = df1 |> Frame.filterRowValues (fun row ->
recdSet.Contains(row.GetAs<float>("ts"))
Some other things that might be useful:
You can replace row.GetAs<float>("ts") with just row?ts (which always returns float and works only when you have a fixed name, like "ts", but it makes the code nicer)
Comparing float values might not be the best thing to do (because of floating point imprecisions, this might not always work as expected).

Resources