Python chess: Check for passed pawns - chess

In a chess position, I wish to check whether any passed pawn exists for white.
Is it possible to do so using the python-chess library? If not, how can I implement it?
def checkForPassedPawn(position: chess.Board, side_to_move: chess.Color):
# ... check for passed pawn
# return a boolean value
I could not find any built-in method that detects passed pawns.

You'll have to look at the pawn positions yourself. There are many ways to do that. For instance, you could take the board's string representation as a starting point:
r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P p . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R
This is the kond of string you get with str(position).
Then you could put each column in a separate list:
lines = str(position).replace(" ", "").splitlines()
columns = list(zip(*lines))
This gives you:
[
('r', 'p', '.', '.', '.', '.', 'P', 'R'),
('n', 'p', '.', '.', '.', '.', 'P', 'N'),
('b', '.', '.', 'p', '.', '.', 'P', 'B'),
('q', '.', '.', 'P', '.', '.', 'P', 'Q'),
('k', '.', '.', 'p', '.', '.', '.', 'K'),
('b', 'p', '.', '.', 'P', '.', '.', 'B'),
('n', 'p', '.', '.', '.', '.', 'P', 'N'),
('r', 'p', '.', '.', '.', '.', 'P', 'R')
]
It the current player is white, you then can check for the left most "P" in each tuple where it has a "p" more left to it, either in the current tuple, the previous one, or the next one.
For the black player, you would use a similar logic and it might be useful to first reverse the tuples in that case.
Here is an implementation of that idea:
import chess
def checkForPassedPawn(position: chess.Board, side_to_move: chess.Color):
selfpawn = "pP"[side_to_move]
otherpawn = "Pp"[side_to_move]
lines = str(position).replace(" ", "").splitlines()
if side_to_move == chess.BLACK:
lines.reverse()
# turn rows into columns and vice versa
columns = list(zip(*lines))
for colnum, col in enumerate(columns):
if selfpawn in col:
rownum = col.index(selfpawn)
if (otherpawn not in col[:rownum]
and (colnum == 0 or otherpawn not in columns[colnum-1][:rownum])
and (colnum == 7 or otherpawn not in columns[colnum+1][:rownum])):
return f"{'abcdefgh'[colnum]}{rownum+1}"
position = chess.Board()
position.push_san("e4")
position.push_san("d5")
position.push_san("f4")
position.push_san("e5")
position.push_san("exd5")
position.push_san("c5") # Now white pawn at d5 is a passed pawn
print(position)
passedpawn = checkForPassedPawn(position, chess.WHITE)
print("passed white pawn:", passedpawn)
position.push_san("d4")
position.push_san("e4") # Now black pawn at e4 is a passed pawn
print(position)
passedpawn = checkForPassedPawn(position, chess.BLACK)
print("passed black pawn:", passedpawn)
Output:
r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P p . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R
passed white pawn: d4
r n b q k b n r
p p . . . p p p
. . . . . . . .
. . p P . . . .
. . . P p P . .
. . . . . . . .
P P P . . . P P
R N B Q K B N R
passed black pawn: e4

Related

Perl: Combine duplicated keys in Hash of Array

I having issues with this and wondering if someone could provide some help. I'm parsing a .txt file and want to combine duplicated keys and it's values. Essentially, for each identifier I want to store it's height value. Each "sample" has 2 entries (A & B). I have the file stored like this:
while(...){
#data= split ("\t", $line);
$curr_identifier= $data[0];
$markername= $data[1];
$position1= $data[2];
$height= $data[4];
if ($line >0){
$result[0] = $markername;
$result[1] = $position1;
$result[2] = $height;
$result[3] = $curr_identifier;
$data{$curr_identifier}= [#result];
}
}
This seems to work fine, but my issue is that when I send this data to below function. It prints the $curr_identifier twice. I only want to populate unique identifiers and check for the presence of it's $height variable.
if (!defined $data{$curr_identifier}[2]){
$output1= "no height for both markers- failed";
} else {
if ($data{$curr_identifier}[2] eq " ") {
$output1 = $markername;
}
}
print $curr_identifier, $output1 . "\t" . $output1 . "\n";
Basically, if sample height is present for both markers (A&B), then output is both markers.
'1', 'A', 'B'
If height is not present, then output is empty for reported marker.
'2', 'A', ' '
'3', ' ', 'B'
My current output is printing out like this:
1, A
1, B
2, A
2, ' '
3, ' '
3, B'
_DATA_
Name Marker Position1 Height Time
1 A A 6246 0.9706
1 B B 3237 0.9706
2 A 0
2 B B 5495 0.9775
3 A A 11254 0.9694
3 B 0
Your desired output can essentially be boiled down to these few lines of perl code:
while (<DATA>) {
($name,$mark,$pos,$heig,$time) = split /\t/;
print "'$name','$mark','$pos'\n";
}
__DATA__
... your tab-separated data here ...

SAS Proc IML Optimization

proc iml;
start f_prob(beta) global(one_m_one, pone_m_one);
p = nrow(one_m_one);
td = j(p,3,0.);
a = 1;
do i = 1 to p;
td[i,1] = exp((one_m_one[i,1])*(beta[1]) + (one_m_one[i,2])*(beta[2]) + (one_m_one[i,3])*(beta[3]) + (one_m_one[i,4])*(beta[4]) + (one_m_one[i,5])*(beta[5]) + (one_m_one[i,6])*(beta[6]) + (one_m_one[i,7])*(beta[7]) + (one_m_one[i,8])*(beta[8]) + (one_m_one[i,9])*(beta[9]) + (one_m_one[i,10])*(beta[10]));
do j = a to 11+a;
td[i,2] = td[i,2] + exp((pone_m_one[j,1])*(beta[1]) + (pone_m_one[j,2])*(beta[2]) + (pone_m_one[j,3])*(beta[3]) + (pone_m_one[j,4])*(beta[4]) + (pone_m_one[j,5])*(beta[5]) + (pone_m_one[j,6])*(beta[6]) + (pone_m_one[j,7])*(beta[7]) + (pone_m_one[j,8])*(beta[8]) + (pone_m_one[j,9])*(beta[9]) + (pone_m_one[j,10])*(beta[10]));
end;
a = a + 12;
end;
td[,3] = td[,1]/td[,2];
f = 1;
do i = 1 to p;
f = f*td[i,3];
end;
return(f);
finish f_prob;
/* Set up the constraints: sum(x)=0 */
/* x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 SIGN VALUE */
con = {. . . . . . . . . . . ., /* specify lower bounds */
. . . . . . . . . . . ., /* specify upper bounds */
1 1 1 1 1 1 1 1 1 1 0 0}; /* constraints */
beta0 = j(1,10,0);
optn = {1,4};
call nlpnra(rc, result, "f_prob", beta0, optn) blc=con;
Hi, I am trying to optimise the function f that has 10 parameters in it with a constraint of all 10 parameters sum up to zero.
Can anyone suggest how can I write the code for the last part so that i can optimise f and get the results i want? Thanks in advance.
The documentation provides an example of how to specify a linear constraint matrix. For your example, use a 3 x 12 matrix.
On the first row (columns 1:10) put any lower-bound constraints for the parameters.
On the second row (columns 1:10) put any upper-bound constraints for the parameters.
On the third row, put all ones in columns 1:10. Put a 0 in column 11 to indicate the EQUAL sign. Put 0 in the 12th column to indicate the value of the constraint.
The code looks like this:
/* Set up the constraints: sum(x)=0 */
/* x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 SIGN VALUE */
con = {. . . . . . . . . . . ., /* specify lower bounds */
. . . . . . . . . . . ., /* specify upper bounds */
1 1 1 1 1 1 1 1 1 1 0 0}; /* constraints */
call nlpnra(rc, result, "f_prob", beta, optn) blc=con;
The last line specifies the coefficients of the matrix expression c*x = 0, where c = {1 1 ... 1} contains the of the third row.

Spark SQL: Transforming some rows into columns

Is there a way to transform a org.apache.spark.sql.DataFrame like this
Predictor icaoCode num1 num2
P1 OTHH 1.1 1.2
P1 ZGGG 2.1 2.2
P2 OTHH 3.1 3.2
P2 ZGGG 4.1 4.2
P3 OTHH 5.1 5.2
P3 ZGGG 6.1 6.2
. . . .
. . . .
. . . .
into a DataFrame like this?
icaoCode P1.num1 P1.num2 P2.num1 P2.num2 P3.num1 P3.num2 ...
OTHH 1.1 1.2 3.1 3.2 5.1 5.2 ...
ZGGG 2.1 2.2 4.1 4.2 6.1 6.2 ...
. . . . . . . ...
. . . . . . . ...
. . . . . . . ...
There can be an arbitrary number of values for Predictor and for icaoCode.
With Spark 1.6.0, there is a pivot function to transform/transpose your data. In your case it requires some preprocessing to get the data ready for pivot. Here an example how I'd do it:
def doPivot(): Unit = {
val sqlContext: SQLContext = new org.apache.spark.sql.SQLContext(sc)
// dummy data
val r1 = Input("P1", "OTHH", 1.1, 1.2)
val r2 = Input("P1", "ZGGG", 2.1, 2.2)
val r3 = Input("P2", "OTHH", 3.1, 3.2)
val records = Seq(r1, r2, r3)
val df = sqlContext.createDataFrame(records)
// prepare data for pivot
val fullName: ((String, String) => String) = (predictor: String, num: String) => {
predictor + "." + num
}
val udfFullName = udf(fullName)
val dfFullName = df.withColumn("num1-complete", udfFullName(col("predictor"), lit("num1")))
.withColumn("num2-complete", udfFullName(col("predictor"), lit("num2")))
val dfPrepared = dfFullName.select(col("icaoCode"), col("num1") as "num", col("num1-complete") as "value")
.unionAll(dfFullName.select(col("icaoCode"), col("num2") as "num", col("num2-complete") as "value"))
// transpose/pivot dataframe
val dfPivoted = dfPrepared.groupBy(col("icaoCode")).pivot("value").mean("num")
dfPivoted.show()
}
case class Input(predictor: String, icaoCode: String, num1: Double, num2: Double)
The final dataframe should work for you:
+--------+-------+-------+-------+-------+
|icaoCode|P1.num1|P1.num2|P2.num1|P2.num2|
+--------+-------+-------+-------+-------+
| OTHH| 1.1| 1.2| 3.1| 3.2|
| ZGGG| 2.1| 2.2| null| null|
+--------+-------+-------+-------+-------+

Confused about behavior of setResultsName in Pyparsing

I am trying to parse a few SQL statements. Here is a sample:
select
ms.member_sk a,
dd.date_sk b,
st.subscription_type,
(SELECT foo FROM zoo) e
from dim_member_subscription_all p,
dim_subs_type
where a in (select moo from t10)
I am interested in getting tables only at this time. So I would like to see
[zoo, dim_member_subscription_all, dim_subs_type] & [t10]
I have put together a small script looking at Paul McGuire's example
#!/usr/bin/env python
import sys
import pprint
from pyparsing import *
pp = pprint.PrettyPrinter(indent=4)
semicolon = Combine(Literal(';') + lineEnd)
comma = Literal(',')
lparen = Literal('(')
rparen = Literal(')')
update_kw, volatile_kw, create_kw, table_kw, as_kw, from_kw, \
where_kw, join_kw, left_kw, right_kw, cross_kw, outer_kw, \
on_kw , insert_kw , into_kw= \
map(lambda x: Keyword(x, caseless=True), \
['UPDATE', 'VOLATILE', 'CREATE', 'TABLE', 'AS', 'FROM',
'WHERE', 'JOIN' , 'LEFT', 'RIGHT' , \
'CROSS', 'OUTER', 'ON', 'INSERT', 'INTO'])
select_kw = Keyword('SELECT', caseless=True) | Keyword('SEL' , caseless=True)
reserved_words = (update_kw | volatile_kw | create_kw | table_kw | as_kw |
select_kw | from_kw | where_kw | join_kw |
left_kw | right_kw | cross_kw | on_kw | insert_kw |
into_kw)
ident = ~reserved_words + Word(alphas, alphanums + '_')
table = Combine(Optional(ident + Literal('.')) + ident)
column = Combine(Optional(ident + Literal('.')) + (ident | Literal('*')))
column_alias = Optional(Optional(as_kw).suppress() + ident)
table_alias = Optional(Optional(as_kw).suppress() + ident).suppress()
select_stmt = Forward()
nested_table = lparen.suppress() + select_stmt + rparen.suppress() + table_alias
table_list = delimitedList((nested_table | table) + table_alias)
column_list = delimitedList((nested_table | column) + column_alias)
txt = """
select
ms.member_sk a,
dd.date_sk b,
st.subscription_type,
(SELECT foo FROM zoo) e
from dim_member_subscription_all p,
dim_subs_type
where a in (select moo from t10)
"""
select_stmt << select_kw.suppress() + column_list + from_kw.suppress() + \
table_list.setResultsName('tables', listAllMatches=True)
print txt
for token in select_stmt.searchString(txt):
pp.pprint(token.asDict())
I am getting the following nested output. Can anybody please help me understand what I am doing wrong?
{ 'tables': ([(['zoo'], {}), (['dim_member_subscription_all', 'dim_subs_type'], {})], {})}
{ 'tables': ([(['t10'], {})], {})}
searchString will return a list of all matching ParseResults - you can see the tables value of each using:
for token in select_stmt.searchString(txt):
print token.tables
Giving:
[['zoo'], ['dim_member_subscription_all', 'dim_subs_type']]
[['t10']]
So searchString found two SELECT statements.
Recent versions of pyparsing support summing this list into a single consolidated using Python builtin sum. Accessing the tables value of this consolidated result looks like this:
print sum(select_stmt.searchString(txt)).tables
[['zoo'], ['dim_member_subscription_all', 'dim_subs_type'], ['t10']]
I think the parser is doing all you want, you just need to figure out how to process the returned results.
For further debugging, you should start using the dump method on ParseResults to see what you are getting, which will print the nested list of returned tokens, and then a hierarchical tree of all named results. For your example:
for token in select_stmt.searchString(txt):
print token.dump()
print
prints:
['ms.member_sk', 'a', 'dd.date_sk', 'b', 'st.subscription_type', 'foo', 'zoo', 'dim_member_subscription_all', 'dim_subs_type']
- tables: [['zoo'], ['dim_member_subscription_all', 'dim_subs_type']]
['moo', 't10']
- tables: [['t10']]

T-SQL on XML (using XQuery)

I have the below XML
<myroot>
<scene>
<sceneId>983247</sceneId>
<item>
<coordinates>
<coordinate>0</coordinate>
<coordinate>1</coordinate>
<coordinate>2</coordinate>
<coordinate>3</coordinate>
</coordinates>
<Values>
<Value>34</Value>
<Value>541</Value>
<Value>255</Value>
<Value>332</Value>
</Values>
</item>
</scene>
</myroot>
How can I get using TSQL the following result:
Col1 Col2
0 34
1 541
2 255
3 332
Thanks,
M
This XPath 2.0 expression:
/myroot/scene/item/
string-join(for $pos in (0 to max(*/count(*)))
return string-join(for $col in (1 to max(count(*)))
return if ($pos=0)
then concat('Col',$col)
else *[$col]/*[$pos],
' '),
'
')
Output:
Col1 Col2
0 34
1 541
2 255
3 332
Here's my XML noob approach.
If you only trust the element sequencing, and not the coordinate values themselves being a sequence:
select
coordinate = max(case when element = 'coordinate' then elemval end)
, value = max(case when element = 'Value' then elemval end)
from (
select
element = row.value('local-name(.)','varchar(32)')
, elemval = row.value('.','int')
, position = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
from #xml.nodes('/myroot/scene/item/*/*') a (row)
) a
group by position
Alternatively written as two .nodes() and a JOIN (you get the idea).
If do you trust the coordinate numbering to be a sequence starting at zero:
select
coordinate = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
- 1
, value = row.value('.','int')
from #xml.nodes('/myroot/scene/item/Values/*') a (row)
If you only trust the coordinate numbering to be a sequence, but from an arbitrary seed:
select
coordinate = row.value('for $s in . return count(../*[. << $s]) + 1', 'int')
+ row.value('(/myroot/scene/item/coordinates/coordinate)[1]','int')
- 1
, value = row.value('.','int')
from #xml.nodes('/myroot/scene/item/Values/*') a (row)
Paths can be abbreviated:
/myroot/scene/item/*/* -> //item/*/*
/myroot/scene/item/Values/* -> //Values/*
/myroot/scene/item/coordinates/coordinate -> //coordinate
But I don't know the wisdom of this either way.
//item/*/* can probably be made more specific, so that it only includes coordinate and Value edge nodes, but I don't know the syntax.