IF & IF OR & AND IF Statements (Google Sheets) - google-sheets

Trying to create an automated checker. If people choise the rights answers from a Dropdown box they will see the msg: "You May Now Consult" if not they will see "You shall not pass"
I have the following code:
=IF(OR(C8="1", "2")(D8="Yes")(E8="Yes")(G8="Reusable")(F8="Yes"), "You May now Consult", "You Shall Not Pass")
The issue is just the first part, C8. Since it's a dropdown box people can choise multiple answers.
Imagine there are the numbers 1-5 in the dropdown box, but I only want the true statement to be if they choise 1 or 2. The issue now is If I put in number 3 it will give me the error code #VALUE! error.
How Could i create this code so that if they choose numbers 3-5 it will give the error msg "You Shall not Pass"?
Sorry for my explanation as I never really coded anything and this is my first project.
Thanks in advance!
Tried to add the IF(NOT statement but it does not seem to match with the (IF(OR statement.

You can fix syntax errors in the formula like this:
=if(
or( C8 = "1", C8 = "2", D8 = "Yes", E8 = "Yes", G8 = "Reusable", F8 = "Yes"),
"You May now Consult",
"You Shall Not Pass"
)

use:
=IF((C8="1")+(C8="2")+(D8="Yes")+(E8="Yes")+(G8="Reusable")+(F8="Yes"),
"You May now Consult", "You Shall Not Pass")

Your formula:
IF(
OR(
C8=1,
C8=2,
D8="Yes",
E8="Yes",
G8="Reusable",
F8="Yes"
),
"You May now Consult",
"You Shall Not Pass"
)
When you use an OR() function, it returns true whenever any of the conditions are matched, in you case, either C8 is 1 or 2, or D8 or E8 or F8 is "Yes", or G8 is "Reusable".
So, even if you put a 3 into C8, if there are "Yes" in any of D8:F8, or "Reusable" is shown in G8, it will still returns TRUE.
But if the value of C8 must be 1 or 2, in that case, you need a AND():
IF(
AND(
OR(
C8=1,
C8=2,
),
OR(
D8="Yes",
E8="Yes",
G8="Reusable",
F8="Yes"
)
),
"You May now Consult",
"You Shall Not Pass"
)
With this formula, it will return TRUE only when C8 is equal to 1 or 2 AND either D8:F8 contains a "Yes" or G8 equals to "Reusable"

Related

Roblox - invalid argument #2 to 'remove' (number expected, got string)

so I have a simple problem that can probably be easily fixed. My script randomly chooses a string from a table. After it has chosen it ad displayed it, it removes it from the table. But when I try to do that, I get this error, invalid argument #2 to 'remove' (number expected, got string). Here is my script.
local textTable = {
"What is this?",
"What is that?",
"What would match this statement?",
"Pick the option that would match the image."
}
while wait(2) do
local choice = textTable[math.random(1,#textTable)]
script.Parent:WaitForChild("ComputerGui").Game1.TextLabel.Text = choice
table.remove(textTable, choice)
choice = textTable[math.random(1,#textTable)]
end
I have looked into this but nothing has helped my situation. Any help appreciated!
maybe try
while wait(2) do
if #textTable == 0 then
break
end
local choice = math.random(1,#textTable)
script.Parent:WaitForChild("ComputerGui").Game1.TextLabel.Text = textTable[choice]
table.remove(textTable, choice)
choice = math.random(1,#textTable)
end
edit: just read the comments, added if statement check

Check if a list of dates falls between any one list of dates

I have a spreadsheet like this:
A B C D
01 11/10/21 25/09/21 10/10/21
02 29/11/21
03 17/01/22 17/12/21 30/01/22
04 07/03/22
05 25/04/22 09/04/22 25/04/22
06 13/06/22 25/06/22 17/07/22
07 01/08/22
08 19/09/22 24/09/22 09/10/22
09 07/11/22
10 26/12/22 16/12/22 31/01/23
11 13/02/23
12 03/04/23
Basically, the dates in the A column are my data.
The dates in B and C represent intervals. So, B1 and C1 mean "from 25/09/21 to 10/10/21".
I can easily have this in D1, to tell me if the date in A1 falls between B1 and C1:
D1 => =AND(A1 > B1, A1 < C1)
But, I need it to tell me if that dates falls in ANY one of those. So, I can write:
D1 => =OR(AND(A1>B1, A1<C1), AND(A1>B2, A1<C2), ..., AND(A3>B12, A1<C12))
OK, it's ugly, but it does the job. I really did think I could get away with this.
But...
Then I need to repeat the process for ALL of them (A1, B1, C1), comparing EACH one with EACH range on the right. Like this:
D1 -> =OR(AND(A1>B1, A1<C1), AND(A1>B2, A1<C2), ..., AND(A1>B12, A1<C12))
D2 -> =OR(AND(A2>B1, A2<C1), AND(A2>B2, A2<C2), ..., AND(A2>B12, A2<C12))
D3 -> =OR(AND(A3>B1, A3<C1), AND(A3>B2, A3<C2), ..., AND(A3>B12, A3<C12))
And it NEEDS to be written like this (ugh) since smart cut&pasting will mess up the lot.
My current solution is totally terrible.
I assign this to the first one:
=OR(
AND(A1>$C$1 ,A1<$D$1 ),
AND(A1>$C$2 ,A1<$D$2 ),
AND(A1>$C$3 ,A1<$D$3 ),
AND(A1>$C$4 ,A1<$D$4 ),
AND(A1>$C$5 ,A1<$D$5 ),
AND(A1>$C$6 ,A1<$D$6 ),
AND(A1>$C$7 ,A1<$D$7 ),
AND(A1>$C$8 ,A1<$D$8 ),
AND(A1>$C$9 ,A1<$D$9 ),
AND(A1>$C$10,A1<$D$10),
AND(A1>$C$11,A1<$D$11),
AND(A1>$C$12,A1<$D$12),
AND(A1>$C$13,A1<$D$13),
AND(A1>$C$14,A1<$D$14),
AND(A1>$C$15,A1<$D$15)
)
(I came up with this as I wrote this question)
And then paste it again to all of the others. That way, the smart paste will make sure A1 becomes A2 in the second row, and so on. However, it just feels. So. Ugly.
Is there a better way to do this?
Bonus question: how do I make the date in A1 RED if D1 is "TRUE"?
Thanks in advance.
In D2 add formula:
=ArrayFormula(IF(LEN(A2:A),(A2:A>B2:B)*(A2:A<C2:C)>0,))
Bonus:
Add conditional formatting rule for range A2:A:
=IF(LEN(A2),(A2>$B$2:B)*(A2<$C$2:C)>0,)
Try this formula in cell D1 and drag down:
=ArrayFormula(IF(SUM((A1>$B$1:$B$12)*(A1<$C$1:$C$12))>0;TRUE;FALSE))
For the question related to conditional formatting, select the range A1:A12 and apply this custom formula as a rule:
=D1=TRUE
Finally, this is the result that we got:
You can find an example here.

How do I tell my app to read exactly what the string contains?

Stumbled on an issue I can't seem to figure out. I have an app that spits out a certain amount of points depending what the string is so if someone says "not 1" then my app will show -4 points for number 1. If someone says "its 2" then the app will award 12 points for 2.
So now my issue is, If someone says "its 2" and awards 12 points which is great, exactly what I want. But when someone says "its not 2" it still awards 12 points to 2 because it contains the word "its", when I want it to show -4 points.
|| vote.lowercased().contains("its")
|| vote.lowercased().contains("its not")
I want it to be able to see if it contains exactly "its not" then it will know to -4 points.
If you want to distinguish its and its not you have to check for the longer string first
if vote.lowercased().contains("its not") {
// -4 points
} else if vote.lowercased().contains("its") {
// 12 points
}

COBOL Beer on the Wall Program

I'm making the "99 Bottles" program, but with user input on how many to take down. I'm very new to COBOL and I'm definitely overlooking something simple or just completely thinking about this the wrong way.
The following is what I currently have:
IDENTIFICATION DIVISION.
PROGRAM-ID. HW.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 COUNTER PIC S99.
01 BOTTLES PIC Z9.
01 BOTTLES-REMAINING PIC Z9.
01 NUM PIC s9(02) VALUE 0.
PROCEDURE DIVISION.
PERFORM VARYING COUNTER FROM 99 BY NUM UNTIL COUNTER = 0
DISPLAY "How many bottles would you like to take down?"
ACCEPT NUM
MOVE COUNTER to Bottles
subtract NUM FROM COUNTER GIVING BOTTLES-REMAINING
DISPLAY SPACES
EVALUATE COUNTER
WHEN 1
DISPLAY " 1 bottle of beer on the wall, "
" 1 bottle of beer."
DISPLAY "Take one down and pass it around, "
"no more bottles of beer on the wall."
WHEN 2 Thru 99
DISPLAY BOTTLES " bottles of beer on the wall, "
BOTTLES " bottles of beer."
DISPLAY "Take one down and pass it around, "
BOTTLES-REMAINING
" bottles of beer on the wall."
END-EVALUATE
END-PERFORM
GOBACK.
I need to make the NUM clause negative in the following statement (or the data division) so it will subtract from the counter:
PERFORM VARYING COUNTER FROM 99 BY NUM UNTIL COUNTER = 0
I see a few issues here.
First, and this is from admittedly faded memory, but I seem to recall that the VARYING clause required a constant value for the delta. I don't think you can use an actual changing NUM to do this.
So your loop would be better off not using the VARYING clause and instead be something like (code here may not be syntactically correct COBOL, it's meant more to show intent and/or method):
set counter to 99
perform until counter = 0
blah blah blah then change counter
end perform
Second, your little ditty doesn't make sense any more if you're allowed to remove more than one bottle at a time. The statements for the third stanza of the rhyme should be modified similarly to the bottles-left stanza:
evaluate num
when 1
display "Take one down and pass it around, "
when 2 thru 99
display "Take ", num, " down and pass them around, "
end evaluate
And, finally, you probably want to avoid the situation where you remove more bottles than you have available (or less than one, for that matter). That can be done by silently enforcing those limits (clamping) immediately after getting the user input:
accept num
if num is less than one
set num to one
end if
if num is greater than counter
set num to counter
end if
You could also complain and require the user to enter a valid quantity but the easiest solution is probably just to clamp it.

Wiki-fying a text using LPeg

Long story coming up, but I'll try to keep it brief. I have many pure-text paragraphs which I extract from a system and re-output in wiki format so that the copying of said data is not such an arduous task. This all goes really well, except that there are no automatic references being generated for the 'topics' we have pages for, which end up needing to be added by reading through all the text and adding it in manually by changing Topic to [[Topic]].
First requirement: each topic is only to be made clickable once, which is the first occurrence. Otherwise, it would become a really spammy linkfest, which would detract from readability. To avoid issues with topics that start with the same words
Second requirement: overlapping topic names should be handled in such a way that the most 'precise' topic gets the link, and in later occurrences, the less precise topics do not get linked, since they're likely not correct.
Example:
topics = { "Project", "Mary", "Mr. Moore", "Project Omega"}
input = "Mary and Mr. Moore work together on Project Omega. Mr. Moore hates both Mary and Project Omega, but Mary simply loves the Project."
output = function_to_be_written(input)
-- "[[Mary]] and [[Mr. Moore]] work together on [[Project Omega]]. Mr. Moore hates both Mary and Project Omega, but Mary simply loves the [[Project]]."
Now, I quickly figured out a simple or complicated string.gsub() could not get me what I need to satisfy the second requirement, as it provides no way to say 'Consider this match as if it did not happen - I want you to backtrack further'. I need the engine to do something akin to:
input = "abc def ghi"
-- Looping over the input would, in this order, match the following strings:
-- 1) abc def ghi
-- 2) abc def
-- 3) abc
-- 4) def ghi
-- 5) def
-- 6) ghi
Once a string matches an actual topic and has not been replaced before by its wikified version, it is replaced. If this topic has been replaced by a wikified version before, don't replace, but simply continue the matching at the end of the topic. (So for a topic "abc def", it would test "ghi" next in both cases.)
Thus I arrive at LPeg. I have read up on it, played with it, but it is considerably complex, and while I think I need to use lpeg.Cmt and lpeg.Cs somehow, I am unable to mix the two properly to make what I want to do work. I am refraining from posting my practice attempts as they are of miserable quality and probably more likely to confuse anyone than assist in clarifying my problem.
(Why do I want to use a PEG instead of writing a triple-nested loop myself? Because I don't want to, and it is a great excuse to learn PEGs.. except that I am in over my head a bit. Unless it is not possible with LPeg, the first is not an option.)
So... I got bored and needed something to do:
topics = { "Project", "Mary", "Mr. Moore", "Project Omega"}
pcall ( require , 'luarocks.require' )
require 'lpeg'
local locale = lpeg.locale ( )
local endofstring = -lpeg.P(1)
local endoftoken = (locale.space+locale.punct)^1
table.sort ( topics , function ( a , b ) return #a > #b end ) -- Sort by word length (longest first)
local topicpattern = lpeg.P ( false )
for i = 1, #topics do
topicpattern = topicpattern + topics [ i ]
end
function wikify ( input )
local topicsleft = { }
for i = 1 , #topics do
topicsleft [ topics [ i ] ] = true
end
local makelink = function ( topic )
if topicsleft [ topic ] then
topicsleft [ topic ] = nil
return "[[" .. topic .. "]]"
else
return topic
end
end
local patt = lpeg.Ct (
(
lpeg.Cs ( ( topicpattern / makelink ) )* #(-locale.alnum+endofstring) -- Match topics followed by something thats not alphanumeric
+ lpeg.C ( ( lpeg.P ( 1 ) - endoftoken )^0 * endoftoken ) -- Skip tokens that aren't topics
)^0 * endofstring -- Match adfinum until end of string
)
return table.concat ( patt:match ( input ) )
end
print(wikify("Mary and Mr. Moore work together on Project Omega. Mr. Moore hates both Mary and Project Omega, but Mary simply loves the Project.")..'"')
print(wikify("Mary and Mr. Moore work on Project Omegality. Mr. Moore hates Mary and Project Omega, but Mary loves the Projectaaa.")..'"')
I start off my making a pattern which matches all the different topics; we want to match the longest topics first, so sort the table by word length from longest to shortest.
Now we need to make a list of the topics we haven't seen in the current input.
makelink quotes/links the topic if we haven't seen it already, otherwise leaves it be.
Now for the actual lpeg stuff:
lpeg.Ct packs all our captures into a table (to be concated together for output)
topicpattern / makelink captures a topic, and passes in through our makelink function.
lpeg.Cs substitutes the result of makelink back in where the match of the topic was.
+ lpeg.C ( ( lpeg.P ( 1 ) - locale.space )^0 * locale.space^1 ) if we didn't match a topic, skip a word (that is, not spaces followed by a space)
^0 repeat.
Hope thats what you wanted :)
Daurn
Note: Edited code, description no longer correct
So why don't you use string.find? It search only for a first topic occurrence and gives you its starting index and length. All you have to do is to add '[[' to a result.
For each chunk, copy the topics table and when the first occurency has been found, remove it.
Sort topics by length, most long first so that the most relevant topic will be found first
LPeg is a good tool, but it's not necessary to use it here.

Resources