I have a variable v in my program, and it may take any value from the set of values
"a", "b", "c", ..., "z"
And my goal is to execute some statement only when v is not "x", "y", or "z".
I have tried,
for C-like languages (where equality operators compare the actual string values; e.g. c#, javascript, php)
if (v != "x" || v != "y" || v != "z")
{
// the statements I want to be executed
// if v is neither "x", nor "y", nor "z"
}
for Pascal-like languages (e.g. plsql)
IF (v != 'x' OR v != 'y' OR v != 'z') THEN
-- the statements I want to be executed
-- if v is neither "x", nor "y", nor "z"
END IF;
The statements inside the if condition always get executed. Am I doing anything wrong?
Use &&/AND/and, not ||/OR/or:
v != "x" && v != "y" && v != "z"
Problem
If an if block is always executed, the condition for the if block always evaluates to true. The logical expression must be wrong.
Let us consider v != "x" || v != "y" || v != "z" for each value of v.
When v = "x",
v != "x" becomes "x" != "x", which is false.
v != "y" becomes "x" != "y", which is true.
v != "z" becomes "x" != "z", which is true.
The expression evaluates to false || true || true, which is true.
When v = "y", the expression becomes
"y" != "x" || "y" != "y" || "y" != "z"
or true || false || true, which is true.
When v = "z", the expression becomes
"z" != "x" || "z" != "y" || "z" != "z"
or true || true || false, which is true.
For any other value for v, the expression evaluates to true || true || true, which is true.
Alternatively, consider the truth-table:
│ A B C │
v │ v != "x" v != "y" v != "z" │ A || B || C
───────┼──────────────────────────────────┼──────────────
"x" │ false true true │ true
"y" │ true false true │ true
"z" │ true true false │ true
other │ true true true │ true
As you can see, your logical expression always evaluates to true.
Solution
What you want to do is, find a logical expression that evaluates to true when
(v is not "x")and(v is not "y")and(v is not "z").
The correct construction is,
for C-like languages (eg. c#, javascript-(may need the strict equality operator !==), php)
if (v != "x" && v != "y" && v != "z")
{
// the statements I want to be executed
// if v is neither "x", nor "y", nor "z"
}
for Pascal-like languages plsql
IF (v != 'x' AND v != 'y' AND v != 'z') THEN
-- the statements I want to be executed
-- if v is neither "x", nor "y", nor "z"
END IF;
De Morgan's law
By De Morgan's law, the expression can also be rewritten as (using C-like syntax)
!(v == "x" || v == "y" || v == "z")
meaning
not((v is "x")or(v is "y")or(v is "z")).
This makes the logic a bit more obvious.
Specific languages
Some languages have specific constructs for testing membership in sets, or you can use array/list operations.
sql: v NOT IN ('x', 'y', 'z')
javascript: ["x", "y", "z"].indexOf(v) == -1
python: v not in {"x", "y", "z"}
java: !Arrays.asList("x", "y", "z").contains(v)
java-9 (and above): !Set.of("x", "y", "z").contains(v)
I figured I'd contribute an answer for Bourne shell script, since the syntax is somewhat peculiar.
In traditional/POSIX sh the string equality test is a feature of the [ command (yes, that is a distinct command name!) which has some pesky requirements on quoting etc.
#### WRONG
if [ "$v" != 'x' ] || [ "$v" != 'y'] || [ "$v" != 'z' ]; then
: some code which should happen when $v is not 'x' or 'y' or 'z'
fi
Modern shells like Ksh, Bash, Zsh etc also have [[ which is somewhat less pesky.
#### STILL WRONG
if [[ $v != 'x' || $v != 'y' || $v != 'z' ]]; then
: some code which should happen when $v is not 'x' or 'y' or 'z'
fi
We should highlight the requirement to have spaces around each token, which is something many beginners overlook (i.e. you can't say if[[$v or $v!='y' without whitespace around the commands and operators), and the apparent optionality of quoting. Failing to quote a value is often not a syntax error, but it will lead to grave undesired semantical troubles if you fail to quote a value which needs to be quoted. (More on this elsewhere.)
The obvious fix here is to use && instead of || but you should also note that [[ typically sports support for regular expressions, so you can say something like
if [[ ! $v =~ ^(x|y|z)$ ]]; then
: yeah
fi
and don't forget the trusty old case statement which is quite natural for this, and portable back into the late 1970s:
case $v in
x | y | z)
;; # don't actually do anything in this switch
*) # anything else, we fall through to this switch
yeah
some more yeah
in fact, lots of yeah;;
esac
The trailing double semicolons cause aneurysms at first, but you quickly recover, and learn to appreciate, even love them. POSIX lets you put an opening parenthesis before the match expression so you don't have unpaired right parentheses, but this usage is rather uncommon.
(This is obviously not a suitable answer for Unix shells which are not from the Bourne family. The C family of shells -- including the still somewhat popular tcsh -- use a syntax which is supposedly "C-like" but that's like being unable to tell apart Alice Cooper from the girl who went to Wonderland; and the Fish shell has its own peculiarities which I'm not even competent to comment on.)
You could use something like this, for PHP:
if(strpos('xyz',$v[0])===false)//example 1
//strpos returns false when the letter isn't in the string
//returns the position (0 based) of the substring
//we must use a strict comparison to see if it isn't in the substring
if(!in_array($v[0],array('x','y','z')))//example 2
//example 3
$out=array('x'=>1,'y'=>1,'z'=>1); //create an array
if(!$out[$v[0]]) //check if it's not 1
if(!preg_match('/^[xyz]$/',$v))//example 4, using regex
if(str_replace(array('x','y','z'),'',$v[0]))//example 5
if(trim($v[0],'xyz'))//example 6
For Javascript:
if(~'xyz'.search(v[0]))//example 1(.indexOf() works too)
if(!(v[0] in {x:0,y:0,z:0}))//example 2
if(~['x','y','z'].indexOf(v[0]))//example 3, incompatible with older browsers.
if(!/^[xyz]$/.match(v))//example 4
if(v.replace(/^[xyz]$/))//example 5
For MySQL:
Select not locate(#v,'xyz'); -- example 1
select #v not in ('x','y','z'); -- example 2
-- repetition of the same pattern for the others
For C:
if(!strstr("xyz",v))//example 1, untested
There are more ways, I'm just too lazy.
Use your imagination and just write the one that you like more!
# Pseudocode
midterm <-- INPUT()
IF (midterm >= 90)
{
grade <-- "A"
}
IF ((midterm >= 80) AND (midterm < 90))
{
grade <-- "B"
}
ELSE
{
grade <-- "C"
}
DISPLAY (grade)
#Python
midterm = int(input("Enter your grade here")
if midterm >= 90:
grade = 'A'
if midterm >= 80 and midterm <90:
grade='b'
else:
grade='c'
print(grade)
Why is the output to this question letter grade C and not A? for all the values greater than 90 or lower than 80?
As jasonharper mentions, the else is an alternative to the SECOND if statement you have written, NOT the first.
So if you input 95, the first if will set grade to "A", then the second if won't execute since the conditions are not met, but since the else statement is an alternative to the SECOND if statement and not the first, the else statement will set grade to "C" since the preluding if statement did not run.
The simple fix here is to change the SECOND if statement to an elif statement, so then the second if will become an alternative to the FIRST if and then the else will become the final alternative.
How do i achieve the following pattern, if input is 3?
AA
BBAA
AABBAA
Furthest i can get was:
AA
BBBB
AAAAAA
I have tried the following:
#mod operator used to alternate patterns
pattern_size = int (input ("Input height : "))
for level in range (1, pattern_size +1):
for x in range (level):
# print AA if remainder != 0
if level % 2 != 0:
print ("AA", end = '')
# print BB if remainder = 0
if level % 2 == 0:
print ("BB", end = '')
I guess it is a homework, and you will get more if you will find the solution on your own.
Firstly, if you want to alternate AA and BB when printing on the same level, it must depend on x (because x changes when level does not change). Moreover, each level starts with a different pattern. This way you may want to test (level + x) % 2 == 0 (choose the easy way of testing). If the boolean expression is true, print one pattern, else print the other.
Do not forget to print() without arguments after the x loop.
I prefer simpler usage of range() -- with a single argument. If pattern_size is 3, then the first loop can go through levels 0, 1, 2. However, the second for must loop at least once. Then you must go through range(level + 1).
I am working on a research project with baseball data from retrosheet.org. I want to create variables for the score of each team in each inning (Vis1, Home1, Vis2, Home2, etc). The problem is that the variable for the box score is coded strangely. Each team has its own variable for the whole game and each inning gets one value. Because leading zeros are cut off a value of "12(10)1X" would mean that a team did not score in the first 4 innings, scored once in the fifth, twice in the sixth, ten times in the seventh, once in the eighth, and they did not have to play the ninth because they had won by that point.
Any advice? I'm at a loss. The () confuse me the most.
There is an example in this talk at useR! 2012 that may provide more information specific to your baseball project.
You can find it here.
I'm irish and live in wales and have no clue about baseball but, I think I remember hearing that there can only be a maximum of 9 innings???? (honestly... no clue!!!)
bbscore = function(x)
{
scores = c()
score = unlist(strsplit(x,split=""))
i= 1
while(i<length(score)+1)
{
if(score[i]=="(")
{
scores = c(scores,paste(score[i+1],score[i+2],sep=""))
i = i+4
}
scores = c(scores,score[i])
i = i+1
}
return(scores)
}
> x
[1] "12(10)1X"
> bbscore(x)
[1] "0" "0" "0" "0" "1" "2" "10" "1" "X"
> scores.df = read.csv("GL1995.TXT",header=F)
> head(scores.df$V20)
[1] 200030300 000000000 000300020 000000010 100100010 001002300
1355 Levels: (11)00033102 00000000 000000000 0000000000 ... 710001001
> scores.df$V20 = as.character(scores.df$V20)
> V20.1995.scores = lapply(scores.df$V21, bbscore)
> V20.1995.scores = lapply(scores.df$V20, bbscore)
> V20.1995.scores[[1]]
[1] "2" "0" "0" "0" "3" "0" "3" "0" "0"
> V20.1995.scores[[2]]
[1] "0" "0" "0" "0" "0" "0" "0" "0" "0"
> V20.1995.scores[[3]]
[1] "0" "0" "0" "3" "0" "0" "0" "2" "0"
Of course you'll have to do some furhter manipulations to get them into numbers and deal with X's and also this will break if there are any other unexpected characters, in addition to being beholden to the assumption of 9 innings.
EDIT:
I removed the stipulation for 9 innings and show how to do this for the entire column (assuming that scores you spoke of are indeed the 20th variable in the csv file). Extra porcessing is required for different number of innings. do.call(rbind,...) won't work. find the longest game and append "X"'s to the end to make them all the same length? Maybe? I'm not sure but I think this question has been answered at least.
Late answer, but...
There is a new R package for fetching data from the MLB server including box score and much more. Might be worth a look!
openWar
It's cool that Rebol's PARSE dialect is generalized enough that it can do pattern matching and extraction on symbolic structures as well as on strings. Like this:
; match a single "a" character, followed by any number of "b" chars
>> string-rule: ["a" some "b"]
>> parse "abb" string-rule
== true
>> parse "aab" string-rule
== false
; look for a single apple symbol, followed by any number of bananas
>> block-rule: ['apple some 'banana]
>> parse [apple banana banana] block-rule
== true
>> parse [apple apple banana] block-rule
== false
But let's say I'm looking for a block containing an apple symbol, and then any number of character strings matching the string-rule:
; test 1
>> parse [apple "ab" "abbbbb"] mixed-rule
== true
; test 2
>> parse [apple "aaaa" "abb"] mixed-rule
== false
; test 3
>> parse [banana "abb" "abbb"] mixed-rule
== false
How would I formulate such a mixed-rule? Looking at the documentation it suggests that one can use INTO:
http://www.rebol.net/wiki/Parse_Project#INTO
The seemingly natural answer doesn't seem to work:
>> mixed-rule: ['apple some [string! into ["a" some "b"]]]
While it passes test 1 and correctly returns false for test 3, it incorrectly returns true in test 2. Is this my mistake or a bug in Rebol (I'm using r3 A111)?
Steeve over on the REBOL3 forum suggests this:
only the second string is checked.
Should be:
['apple some [and string! into ["a" some "b" ]]]