Prolog Database: Why is program only running once? - database

I got this code that has to run a database as long as N > Order.
My code only runs once :/ ?
display(N) :-
w(Order,_,Word,Class),
N > Order -> (write(Word), write(' '), write(Class)),
nl, fail .
Thanks in advance!

your problem is the way you use ->
First of all, the code is interpreted as:
display(N) :-
( w(Order,_,Word,Class),
N > Order )
) ->
( write(Word),
write(' '),
write(Class)
),
nl, fail .
-> destroys choice points meaning that it will not try to call w/3 again.
You could (probably) make it work like this:
display(N) :-
(w(Order,_,Word,Class),
N > Order )-> (write(Word), write(' '), write(Class)),
nl, fail .
but in the end it's really ugly code and, as you have seen, prone to bugs. A better way is to use forall/2:
display2(N) :-
forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); true)).
still, this will examine the whole database and print if N>Order. It is a bit unclear from your description if this is the desired behaviour but if you want to stop at the first element that is larger you could do something like:
display2(N) :-
catch((forall(w(Order, _, Word, Class),
(N > Order ->
writef("%t %t \n", [Word,Class]); throw(end))), end, true)).
not the most declarative way to do it but I'm not sure what's the best way to model it without knowing what w/4 is (I assumed that it is some prolog clauses but it could be a predicate accessing a DB though the ODBC layer)

I think you forgot the 'else' branch, and the precedence of (->)/2, that's higher that (,)/2, inhibits the intended order. Try
display(N) :-
w(Order,_,Word,Class),
( N > Order -> write(Word), write(' '), write(Class), nl ; true ),
fail .

Related

Backpatching with OR_ELSE and ALSO in yacc

I am trying to implement Syntax Directed Translation(SDT) using yacc. In the case of boolean expressions I've chosen to adopt Backpatching method. Below is an example of my implementation of logical OR using C in yacc :
simpleexp : simpleexp OR M simpleexp
{
backpatch($1.falselist,$3.quad);
$$.truelist = merge($1.truelist,$4.truelist);
$$.falselist = $4.falselist;
$$.type = TYPE_BOOL;
fprintf(fout, "Rule 64 \t\t simpleexp -> simpleexp OR simpleexp \n");
};
M : /* empty */
{
$$.quad = nextquad();//nextquad returns next available place in quadruples array
};
It does work but my current problem is something else. We are to have an alternate approach for handling logical operation OR_ELSE besides the "Side Effect" approach adopted just for usual OR. Lets go on a little bit more about the problem
Imagine we are dealing with something like simpleexp1 OR simpleexp2(numbers are provided in order to distinct simpleexp s from each other). Using the implemetation of logical OR , as implemented above , we won't evaluate simpleexp2 if simpleexp1 is true. Because we should jump to simpleexp1.truelist which is filled via calling backpatch function called somewhere else later. In case of simpleexp1 OR_ELSE simpleexp2 we want to be sure that simpleexp2 is evaluated , whether the final result will be true or false. For example if simpleexp2 is (x++ == 4) where x is an integer , we want to be sure that the incrementation takes place and the value of x increments by 1 ; however , in the case of simpleexp1 OR simpleexp2 , the value of x won't change if the simpleexp1 is true.
P.S. : I have figured out that in order the simpleexp2 to be evaluated we should fill both the truelist and falselist of simpleexp1 in an order that causes the control flow to be given to the beginning of simpleexp2 , but I don't know what to do next!

AHK: Copying a block of text into an array, modifying, and transferring to another array

Alright so the question is hard to word. I've googled this several times, but usually it turns out I'm not googling the right phrases, and the answer is readily available. I do work as a medical biller for a doctors office, and I have to include diagnosis codes for the office visits. In the Electronic Medical Record program, there's a diagnosis list. The first line is the doctors description, I don't care about that. The second line is an ICD-9 code. Those are old, I don't care about those either. The third line (every third line) contains the ICD-10 code. That's what I need. What I'd like to be able to do is grab the whole list, dump it into an array delimited by new lines, and get rid of every element that doesn't contain a specific string. Then, dump all the kept elements into another array (or the same one, but not separated by 3 like they would be after the removals) and remove that prefixed string that I kept elements based on. After that, I need to click a specific spot (I know how to do this), add exactly four of the arrays elements as text (can't figure this out), hit enter, and keep adding and hitting enter until I've entered all of the array. I will post what I've tried cobble together from google searches if anyone wants to see that mess. But a general explanation on how to do this would also be appreciated. Thanks.
first of all, the stuff I'd be copying would look like this (actual example)
Lumbar stenosis - Primary
ICD-9-CM: 724.02
ICD-10-CM: M48.06
Spondylolisthesis of lumbar region
ICD-9-CM: 738.4
ICD-10-CM: M43.16
Lumbar degenerative disc disease
ICD-9-CM: 722.52
ICD-10-CM: M51.36
Chronic bilateral low back pain with bilateral sciatica
ICD-9-CM: 724.2, 724.3, 338.29
ICD-10-CM: M54.42, M54.41, G89.29
Naturally the list would be much longer.
The string I'd look for to keep the lines would be "ICD-10-CM: ", just so you guys know. I DID try using it as a delimiter, in quotes, but got some really quite weird results. It would have made this problem slightly easier to solve had that worked as the delimiter.
Arrays:={}
RealArray:={}
^j::
sendinput, ^c
sleep 20
bigone:=ClipBoard
sleep 2000
;StringReplace, bigone, newbigone, `n, "DLMTR", All
;Arrays:= StrSplit(newbigone, "DLMTR")
StringSplit, Arrays, bigone, `n
k=4
j=1
loop
{
if (k<Arrays.Max_Index)
{
RealArray%j%=Arrays%k%
j++
k++
k++
k++
}
else
return
}
return
^L::
a=0
loop
{
if (a<RealArray.Max_Index)
{
send RealArray%a%
a++
sendinput, {Space}
if(mod(a,5)==0)
sendinput, {enter}
}
else
return
}
Program
^j collects codes containing "ICD-10", ^k pastes the codes formatted 5 per line
^j::copyit()
^l::pasteit()
copyit()
{
sendinput, ^c
sleep 20
bigone := ClipBoard
sleep 100
global matches
matches := []
numMatches := 0
Loop parse, bigone, `n
Loop parse, A_LoopField, `,
if InStr(A_LoopField, "ICD-10")
matches[++numMatches] := trim( substr(A_LoopField, InStr(A_LoopField, ":") + 1), " `t`n`r")
}
pasteit()
{
global matches
for index, element in matches
{
Send %element%{SPACE}
if mod(index,5) == 0
Send {ENTER}
}
}
Input:
Recurrent major depressive disorder, in partial remission
ICD-9-CM: 296.35
ICD-10-CM: F33.1
ICD-10-CM: F33.2
ICD-9-CM: 296.35
ICD-10-CM: F33.3
ICD-10-CM: F33.4
ICD-9-CM: 296.35
ICD-10-CM: F33.5, ICD-10-CM: X432.6, ICD-10-CM: Y232.6
ICD-10-CM: F33.6
ICD-9-CM: 296.35
Output:
F33.1 F33.2 F33.3 F33.4 F33.5
X432.6 Y232.6 F33.6
Without knowing how the underlying program that you are automating works, I can't tell you when to sleep or send extra ENTERs.
Maybe you can query the state of the screen to determine what to do next (e.g., send codes, extra ENTERs, wait).
I identify the screen state by searching for a small image that uniquely identifies the state the program is in. I make the images using Alt+PrintScrn to capture the entire screen and then use pbrush.exe to crop out small a unique identifying image.
; Search screen for image stored in "images/name.png"
; return true if found, false otherwise
find( name )
{
fname := "images\" . name . ".png"
ImageSearch x, y, 0,0,A_ScreenWidth, A_ScreenHeight, *32 %fname%
return ( ErrorLevel = 0 and x >= 0 and y >= 0 )
}
; Wait for image stored in "images/name.png" to appear on the screen
wait_for( name )
{
tooltip Waiting for %name%, 100,0,1
while !find(name)
sleep 100
}
; business/domain logic bot
automate_screen()
{
if ( find( "logon" ))
do_stuff_to_logon()
else if ( find( "payroll_history" ))
do_some_other_stuff()
else if ( find( "payroll_screen1" ))
{
sendplay Type this on screen1{enter}01{enter}
wait_for( "payroll_screen2" )
sendplay Type this on screen2{enter}
}
}
main()
{
loop
{
automate_screen()
sleep 250
}
}

Writing onto a file in Prolog

Hi I have the following code:
show_result(Squares,MaxRow,MaxCol) :-
show_result(Squares,MaxRow,MaxCol,1), nl.
show_result(_,MaxRow,_,Row) :- Row > MaxRow, !.
show_result(Squares,MaxRow,MaxCol,Row) :-
show_result(Squares,MaxRow,MaxCol,Row,1), nl,
Row1 is Row+1, show_result(Squares,MaxRow,MaxCol,Row1).
show_result(_,_,MaxCol,_,Col) :- Col > MaxCol, !.
show_result(Squares,MaxRow,MaxCol,Row,Col) :-
(memberchk(sq(Row,Col,X),Squares), !, write(X); write('#')),
Col1 is Col+1, show_result(Squares,MaxRow,MaxCol,Row,Col1).
When I run the code it shows the correct output on the screen.
But I want to write it to a file for which I have modified the code in this way:
show_result(Squares,MaxRow,MaxCol,SolutionFile) :-
show_result(Squares,MaxRow,MaxCol,1,SolutionFile),
open(SolutionFile,write,Stream),
nl(Stream), close(Stream).
show_result(_,MaxRow,_,Row,SolutionFile) :- Row > MaxRow, !.
show_result(Squares,MaxRow,MaxCol,Row,SolutionFile) :-
show_result(Squares,MaxRow,MaxCol,Row,1,SolutionFile),
open(SolutionFile,write,Stream),nl(Stream), close(Stream),
Row1 is Row+1,
show_result(Squares,MaxRow,MaxCol,Row1,SolutionFile).
show_result(_,_,MaxCol,_,Col,SolutionFile) :- Col > MaxCol, !.
show_result(Squares,MaxRow,MaxCol,Row,Col,SolutionFile) :-
( memberchk(sq(Row,Col,X),Squares),
!,
open(SolutionFile,write,Stream), write(Stream,X), close(Stream)
; open(SolutionFile,write,Stream), write(Stream,'#'), close(Stream)
),
Col1 is Col+1,
show_result(Squares,MaxRow,MaxCol,Row,Col1,SolutionFile).
This returns 'true' but doesn't write anything to the file.
What do I need to change to get the output written to the file?
Use your original program and:
..., once_to_file(show_result(Squares,MaxRow,MaxCol)), ...
once_to_file(Goal, File) :-
open(File, write, S),
with_output_to(S,once(Goal)),
close(S).
This can be further improved using setup_call_cleanup/3.
But seriously, it would be much better for you to "write" the information into a list via a dcg. In this manner you would have a clean, program for this part too.
although this seems overly inefficient, you could try to change the open/3 mode, from write to append.
Much better would be to pass around the file descriptor, instead of SolutionFile. So I would suggest
show_result(Squares,MaxRow,MaxCol,SolutionFile) :-
open(SolutionFile,write,Stream),
show_result(Squares,MaxRow,MaxCol,1,Stream),
nl(Stream), close(Stream).
and remove all other open/3 from those predicates, writing instead into SolutionFile:
how_result(_,MaxRow,_,Row,SolutionFile) :- Row > MaxRow, !.
show_result(Squares,MaxRow,MaxCol,Row,SolutionFile) :-
show_result(Squares,MaxRow,MaxCol,Row,1,SolutionFile),
nl(SolutionFile),
Row1 is Row+1,
show_result(Squares,MaxRow,MaxCol,Row1,SolutionFile).
show_result(_,_,MaxCol,_,Col,SolutionFile) :- Col > MaxCol, !.
show_result(Squares,MaxRow,MaxCol,Row,Col,SolutionFile) :-
( memberchk(sq(Row,Col,X),Squares),
!,
write(SolutionFile,X)
; write(SolutionFile,'#')
),
Col1 is Col+1,
show_result(Squares,MaxRow,MaxCol,Row,Col1,SolutionFile).
note: untested code.
Since you mention that the output is already correct, an alternative, available in SWI-Prolog, would be to keep the origincal program unchanged, and call it using with_output_to.
Another alternative, use old fashioned IO, prefixing execution with tell/1, and resume after execution with told/0. But this IO modality is deprecated, since it leads to several difficulties...

SQL case in select query

I have following query
Select
a,b,c,
case totalcount
when 0 then 0
else abcd/totalcount
end AS 'd',
case totalcount
when 0 then 0
else defg/totalcount
end AS 'e'
From
Table1
In this query, I have same case statement in select query...Can i make it into single select statement.
"totalcount" is some value... abcd and defg are two column values from table1. If totalcount is zero, i dont want to divide, else I wish to divide to get an average value of abcd and defg.
No, since you seem to be requiring two output columns in your desired resultset... Each Case statement can generate at most one output value.
It doesn't matter how many columns the case statement needs to access to do it's job, or how many different values it has to select from (how many When... Then... expressions), it just matters how many columns you are trying to generate in the final resultset.
At first view, I would say no, since you seem to use the exact same condition leading to different results.
Besides, this looks odd to me, why would you need two SELECT CASE for only one condition? This makes no sense.
Could you be more specific or give a real-world example of what you're trying to ask, with "real" data so that we might better answer your question?
EDIT #1
Given that:
Yes...it's two different fields....and the valud i need is calculated one...which is Value = a/b. But i need to check if b is zero or not
I would still answer no, as if they are two different fields, and you want both results in your result set, then you will need to write two CASE statements, one for each of the fields you need to verify whether it is zero-valued or not. Keep in mind that one CASE statement is equivalent to one single column only. So, if you need to check for a zero value, you are required to check for both independently.
By the way, sorry for my misunderstanding, that must be a language barrier, unfortunately. =) But my requirement for "real" data example holds, since this might light us all up with some other related solutions, we never know! =)
EDIT #2
Considering you have to check for a value of 0, I would perhaps rewrite my code as follows, for the sake of readability:
select a, b, c
, case when condition1 <> 0 then abcd / condition1 else 0 end as Result1
, case when condition2 <> 0 then defg / condition2 else 0 end as Result2
from Table1
In my opinion, it is leaner and swifter in the code, and it is easier to understand what is the intention. But after all, the result would be the same! No offense made here! =)
EDIT #3
After having read your question edit:
"totalcount" is some value... abcd and defg are two column values from table1. If totalcount is zero, i dont want to divide, else I wish to divide to get an average value of abcd and defg.
I say, if it is the average that you're after, why not just use the AVG function which will deal with it internaly, without having to care about zero values?
select a, b, c
, AVG(abcd) as Result1
, AVG(defg) as Result2
from Table1
Plus, considering having no record, the average can only be 0!
I don't know about your database engine, but if it is Oracle or SQL Server, and I think DB2 as well, they support this function.
You need to elaborate more - what is the condition? With what you have entered so far, it looks like you are just using the result of the expression, making the CASE statement redundant.
For example, see my inline comments:
SELECT a,b,c,
case condition
when 0 then 0 --this is unnecessary
else abcd/condition, --this is just using the result of the condition?
case condition
when 0 then 0 --this is unnecessary
else defg/condition --this is just using the result of the condition?
from Table1
so you could just refactor this as:
SELECT a
,b
,c
,expression
,expression
from Table1
if you actually meant the else abcd/condition as evaluate another condition or use a default value then you need to expand on that so we can answer accurately.
EDIT: if you are looking to avoid a divide by zero and you only want to evaluate condition once, then you need to do it outside of the SELECT and use the variable inside the SELECT. I wouldn't be concerned about the performance impact of evaluating it multiple times, if the condition doesn't change then its value should be cached by the query execution engine. Although it could look ugly and unmaintainable, in which case you could possibly factor condition into a function.
If all you're trying to do is avoid dividing by zero, and if it's not critical that an attempt to divide by zero actually produces zero, then you can do the following:
Select
a,b,c,
abcd / NULLIF(totalcount,0) AS 'd',
defg / NULLIF(totalcount,0) AS 'e'
From
Table1
This transforms an attempt to divide by zero into an attempt to divide by NULL, which always produces NULL.
If you need zero and you know that abcd and defg will never be NULL, then you can wrap the whole thing in an ISNULL(...,0) to force it to be zero. If abcd or defg might legitimately be null and you need the zero output if totalcount is zero, then I don't know any other option than using a CASE statement, sorry.
Moreover, since it appears totalcount is an expression, for maintainability you could compute it in a subquery, such as:
Select
a,b,c,
abcd / NULLIF(totalcount,0) AS 'd',
defg / NULLIF(totalcount,0) AS 'e'
From
(
Select
a,b,c,
abcd,
defg,
(... expression goes here ...) AS totalcount
From
Table1
) Data
But if it's a simple expression this may be overkill.
Technically this is possible. I'm not suggesting it's a good idea though!
;with Table1 as
(
select 1 as a, 2 as b, 3 as c, 0 as condition, 1234 as abcd, 4567 AS defg UNION ALL
select 1 as a, 2 as b, 3 as c, 1 as condition, 1234.0 as abcd, 4567 AS defg
)
,
cte AS
(
Select
a,b,c,
case condition
when 0 then CAST(CAST(0 as decimal(18, 6)) as binary(9)) + CAST(CAST(0 as decimal(18, 6)) as binary(9))
else CAST(CAST(abcd/condition as decimal(18, 6)) as binary(9)) + CAST(CAST(defg/condition as decimal(18, 6)) as binary(9))
end AS d
From
Table1
)
Select
a,
b,
c,
cast(substring(d,1,9) as decimal(18, 6)) as d,
cast(substring(d,10,9) as decimal(18, 6)) as e
From cte

"if, then, else" in SQLite

Without using custom functions, is it possible in SQLite to do the following. I have two tables, which are linked via common id numbers. In the second table, there are two variables. What I would like to do is be able to return a list of results, consisting of: the row id, and NULL if all instances of those two variables (and there may be more than two) are NULL, 1 if they are all 0 and 2 if one or more is 1.
What I have right now is as follows:
SELECT
a.aid,
(SELECT count(*) from W3S19 b WHERE a.aid=b.aid) as num,
(SELECT count(*) FROM W3S19 c WHERE a.aid=c.aid AND H110 IS NULL AND H112 IS NULL) as num_null,
(SELECT count(*) FROM W3S19 d WHERE a.aid=d.aid AND (H110=1 or H112=1)) AS num_yes
FROM W3 a
So what this requires is to step through each result as follows (rough Python pseudocode):
if row['num_yes'] > 0:
out[aid] = 2
elif row['num_null'] == row['num']:
out[aid] = 'NULL'
else:
out[aid] = 1
Is there an easier way? Thanks!
Use CASE...WHEN, e.g.
CASE x WHEN w1 THEN r1 WHEN w2 THEN r2 ELSE r3 END
Read more from SQLite syntax manual (go to section "The CASE expression").
There's another way, for numeric values, which might be easier for certain specific cases.
It's based on the fact that boolean values is 1 or 0, "if condition" gives a boolean result:
(this will work only for "or" condition, depends on the usage)
SELECT (w1=TRUE)*r1 + (w2=TRUE)*r2 + ...
of course #evan's answer is the general-purpose, correct answer

Resources