I have this sparql query:
SELECT DISTINCT (COUNT(?bw) AS ?total) (COUNT(?bw_bad) AS ?total_bad) WHERE
{
{
SELECT ?bw WHERE
{
?bw unt:has_bwid ?id
}
}
UNION
{
SELECT ?bw_bad WHERE
{
?bw_bad unt:has_rbdname ?rbd_name_bad .
?bw_bad unt:has_concie_0 ?concie_0 .
FILTER(?concie_0 > 40)
}
}
}
which gives:
total total_bad
"2155"^^<http://www.w3.org/2001/XMLSchema#integer> "46"^^<http://www.w3.org/2001/XMLSchema#integer>
I would like to calculate the percentage of them, which would give (46 / 2155 * 100) 2.13%. How can I do it? I do not care about performance.
My attempt:
SELECT ((COUNT(?bw_bad) AS ?total_bad)/(COUNT(?bw) AS ?total)*100) WHERE
which gives this syntax error:
Encountered " "as" "AS "" at line 10, column 34. Was expecting one of: ")" ... "=" ... "!=" ... ">" ... "<" ... "<=" ... ">=" ... "||" ... "&&" ... "+" ... "-" ... "*" ... "/" ... "in" ... "not in" ... ... ... ... ... ... ...
Change this:
SELECT ((COUNT(?bw_bad) AS ?total_bad)/(COUNT(?bw) AS ?total)*100) WHERE
to this:
SELECT (COUNT(?bw_bad)* 100 / (COUNT(?bw)) as ?total) WHERE
The problem is twofold: you're assigning the intermediate outcome of your aggregates to variables during computation, and then you actually don't assign the final outcome to a variable. You should instead do something like this:
SELECT (COUNT(?bw_bad)/(COUNT(?bw)*100) as ?percentage)
The AS in your select is assigning a name to the aggregate result. Since you are using the aggregates in the computation, there is no need to name them, and that's why the syntax is not allowed.
The use of sub-selects is almost always a mistake, unless they are being used to compute an aggregate needed by the surrounding query. You're not doing that in this case and therefore you can remove the sub-selects for a more efficient query:
SELECT (((COUNT(?bw_bad)/COUNT(?bw))*100) AS ?total_bad)
WHERE
{
{
?bw unt:has_bwid ?id .
}
UNION
{
?bw_bad unt:has_rbdname ?rbd_name_bad .
?bw_bad unt:has_concie_0 ?concie_0 .
FILTER(?concie_0 > 40)
}
}
Related
I am new to Perl and I'm trying to create a simple calculator program, but the rules are different from normal maths. All operations have the same power and the math problem must be solved from left to right.
Here is an example:
123 - 10 + 4 * 10 = ((123 - 10) + 4) * 10 = 1170
8 * 7 / 3 + 2 = ((8 * 7) / 3) + 2 = 20.666
So in the first case the user needs to enter one string: 123 - 10 + 4 * 10.
How do i approach this task?
I'm sorry if it's too much of a general question, but i'm not sure how to even begin. Do i need a counter? Like - every second character of the string is an operator, while the two on the sides are digits.
I'm afraid I'm lazy so I'll parse with a regex and process as I parse.
#!/usr/bin/env perl
#use Data::Dumper;
use Params::Validate (':all');
use 5.01800;
use warnings;
my $string=q{123 - 10 + 4 * 10};
my $result;
sub fee {
my ($a)=validate_pos(#_,{ type=>SCALAR });
#warn Data::Dumper->Dump([\$a],[qw(*a)]),' ';
$result=$a;
};
sub fi {
my ($op,$b)=validate_pos(#_,{ type=>SCALAR},{ type=>SCALAR });
#warn Data::Dumper->Dump([\$op,\$b],[qw(*op *b)]),' ';
$result = $op eq '+' ? $result+$b :
$op eq '-' ? $result-$b :
$op eq '*' ? $result*$b :
$op eq '/' ? $result/$b :
undef;
#warn Data::Dumper->Dump([\$result],[qw(*result)]),' ';
};
$string=~ m{^(\d+)(?{ fee($1) })(?:(?: *([-+/*]) *)(\d+)(?{ fi($2,$3) }))*$};
say $result;
Note the use of (?{...}) 1
To be clear, you are not looking for a regular calculator. You are looking for a calculator that bends the rules of math.
What you want is to extract the operands and operators, then handle them 3 at the time, with the first one being the rolling "sum", the second an operator and the third an operand.
A simple way to handle it is to just eval the strings. But since eval is a dangerous operation, we need to de-taint the input. We do this with a regex match: /\d+|[+\-*\/]+/g. This matches either 1 or more + digits \d or |, 1 or more + of either +-*/. And we do this match as many times as we can /g.
use strict;
use warnings;
use feature 'say';
while (<>) { # while we get input
my ($main, #ops) = /\d+|[+\-*\/]+/g; # extract the ops
while (#ops) { # while the list is not empty
$main = calc($main, splice #ops, 0, 2); # take 2 items off the list and process
}
say $main; # print result
}
sub calc {
eval "#_"; # simply eval a string of 3 ops, e.g. eval("1 + 2")
}
You may wish to add some input checking, to count the args and make sure they are the correct number.
A more sensible solution is to use a calling table, using the operator as the key from a hash of subs designed to handle each math operation:
sub calc {
my %proc = (
"+" => sub { $_[0] + $_[1] },
"-" => sub { $_[0] - $_[1] },
"/" => sub { $_[0] / $_[1] },
"*" => sub { $_[0] * $_[1] }
);
return $proc{$_[1]}($_[0], $_[2]);
}
As long as the middle argument is an operator, this will perform the required operation without the need for eval. This will also allow you to add other math operations that you might want for the future.
Just to read raw input from the user you would simply read the STDIN file handle.
$input = <STDIN>;
This will give you a string, say "123 + 234 - 345" which will have a end of line marker. You can remove this safely with the chomp command.
After that you will want to parse your string to get your appropriate variables. You can brute force this with a stream scanner that looks at each character as you read it and processes it accordingly. For example:
#input = split //, $input;
for $ch (#input) {
if ($ch > 0 and $ch <= 9) {
$tVal = ($tVal * 10) + $ch;
} elsif ($ch eq " ") {
$newVal = $oldVal
} elsif ($ch eq "+") {
# Do addition stuff
}...
}
Another approach would be to split it into words so you can just deal with whole terms.
#input = split /\s+/, $input;
Instead of a stream of characters, as you process the array values will be 123, +, 234, -, and 345...
Hope this points you in the right direction...
I'm trying to concatenate values based on the value of a cell, however, this requires a logical function. I've tried it with both FIND, MATCH and SEARCH, but it's not outputting the expected results.
How do I get it to work expectedly?
Suppose the expected result must be an email address generation where it is in the form of firstname#company.com, but you may have values which looks like "John Doe", "Sales", "John", etc.
This is the functions which I have used, without any success:
MATCH
Function
=IF(COUNTBLANK([#Name]) = 0; IF(MATCH(" "; [#Name]; -1) = 1; CONCATENATE([#Name]; "#company.com"); CONCATENATE(LEFT( [#Name]; FIND( " "; [#Name] ) - 1 ); "#company.com")); "")
Note: Match parameters have been tested amongst -1, 0 and 1. -1 provides the best results.
Result
Where the lookup cell contains "John Doe", the concatenation result looks like John Doe#company.com, and "John" looks like John#company.com. This does not seem to work. When parameters for MATCH changes to 0 or 1, the result is #N/A on all.
FIND
Function
=IF(COUNTBLANK([#Name]) = 0; IF(FIND(" "; [#Name]) = 1; CONCATENATE([#Name]; "#company.com"); CONCATENATE(LEFT( [#Name]; FIND( " "; [#Name] ) - 1 ); "#company.com")); "")
Result
Where the lookup cell contains "John Doe", the concatenation result looks like John#company.com, and "John" looks like "#VALUE!". This does not seem to work effectively.
SEARCH
Function
=IF(COUNTBLANK([#Name]) = 0; IF(SEARCH(" "; [#Name]) <= 1; CONCATENATE([#Name]; "#company.com"); CONCATENATE(LEFT( [#Name]; FIND( " "; [#Name] ) - 1 ); "#company.com")); "")
Result
Where the lookup cell contains "John Doe", the concatenation result looks like John#company.com, and "John" looks like "#VALUE!". This does not seem to work effectively.
It was possible to overcome this issue by using the FIND function, but changing the logical test to check for an error in the find results.
Where you look for a value which is not present, the FIND function will generate a "#VALUE!" error. Simply nest the FIND function into an ISERROR function without any =, < or >. This is the logical test for the FIND function.
=IF(COUNTBLANK([#Name]) = 0; IF(ISERROR(FIND(" "; [#Name])); CONCATENATE([#Name]; "#company.com"); CONCATENATE(LEFT( [#Name]; FIND( " "; [#Name] ) - 1 ); "#company.com")); "")
I am trying to create a way in UltiSnip to take a list of variable names and transform them into a line delimited list of strings (like
you would see in AngularJS). So you type each arg, jump to next placeholder, and above the function is filled in with what you want.
Start with this:
function(FirstArg, SecondArg, ThirdArg)
Hit the CTRL-J (next placeholder)
And Final Result:
[
'FirstArg',
'SecondArg',
'ThridArg',
function(FirstArg, SecondArg, ThirdArg) {
// ... cursor here after hitting CTRL-J
// this would be $0
}
]
Any hints would be great!
Simpler then I thought. This is the function
global !p
def varDeps(args):
result = ""
argList = args.split(",")
for arg in argList:
dep = " " + "'" + arg.strip() + "',\n"
result = result + dep
return result.rstrip()
endglobal
Then use something like this (where this is the third placeholder)
`!p snip.rv = varDeps(t[3])`
function($scope, ${3:deps}) {
//....
}
I have a script which parses an XLSX document and convert it in other format.
In the part where the XLSX file is red, i have an exit condition:
do
{
...
...
...
}
until (uc(trim($worksheet -> get_cell($indexRow, 0) -> value())) eq "");
unfortunately, when I am executing the script, I receive this error:
Can't call method "value" on an undefined value at myfilename.pl line 94
Can anyone give me a hint or explain what what i am doing wrong, please?
by the way, I am a beginner in Perl programming.
the expression
$worksheet -> get_cell($indexRow, 0)
Is not defined. So, no properties can be extracted.
My advice is to re-factor the code this way (but every body have his own advice) (take into considerations spaces in the second condition!):
while (1) # 1 is true
{
...
...
...
# suppose $indexrow has been calculated in the loop.
if ( ! $worksheet -> get_cell($indexRow, 0) ) {
# do something (cell is not defined)
# Cell is empty? (??????? 7 ?)
}
elsif ( ! trim( $worksheet->get_cell($indexRow,0)->value() ) ) {
last; #escape this loop
}
}
Empty string is false, so ! is equivalent to "the string is holding text".
Hope it helps.
I have a hash containing results of matching substrings. I want to print a message if there is no matching between the string. I've tried the following and it didn't work.
foreach (keys %d) {
if ($_ eq "") {
print "no matches"; # and i've tried (if defined $_
} else {
print "$_\n";
}
}
the % d is filled this way (it contains matched substrings) :
foreach (my $i=0;$i<length($seq1)-$k;$i+=1) {
my $common=substr($seq1,$i,$k);
if ($seq2=~/$common/) {
$d{$common}++;
}
}
I think I finally see what you are trying to accomplish. You think that checking if the keys in %d equal the empty string, then there were no matches in your loop. This is false. If there are no matches, then there are no keys, and the loop will never execute.
Unfortunately, you cannot check if %d contains no values that way. You need something like:
unless (%d) {
print "No matches\n";
} else {
print "$_\n" for keys %d;
}
You have an iteration over all existing keys and check if the are an empty string, that's I guess not what you want.
Try
if (defined $d{$_})
or if it is set to "" then
if ($d{$_} eq "")
To be more helpfull, one would have to know how your hash is filled.
You need to initialize also the non matching values. In your code you can add an
if ($seq2=~/$common/) {
$d{$common}++;
}
else
{ $d{$common} = 0 unless (exists($d{common})); }
and then check
if ($d{$_} > 0)