How to get user console input into a Prolog list - list

I am trying to write the user input into a list but am running into two problems. Using this code
getInput([Symptom|List]):-
writeln('Enter Element:'),
read(Symptom),
dif(Symptom,stop),
getInput(List).
getInput([]).
I am able to get symptoms from the user but the output shows the first user input as the Head, and the others as the tail. How do I make the Head "Symptoms" and only ad the user input to the Tail? Secondly, when I change "stop" to "Done" the program no longer stops?
So I was told "Done" doesn't work because it is capitalized. If I want to use a capital word, how would I do that?

This works
get_symptoms(Symptoms) :-
write('Enter Symptom: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Stop"
->
Symptoms = []
;
get_symptoms(Symptoms0),
Symptoms = [Response|Symptoms0]
).
Uses
1. ==/2 instead of dif/2.
2. read_string/5 instead of read/1 so that strings can be entered.
3. write/1 instead of writeln/1 so that input is on same line as prompt.
4. ->/2 instead of separate clauses.
You can change the value of the exit word to something other than "Stop", you can even use single characters like "." if you like.
Notice also that this does not require a cut (!).
Example runs:
?- get_symptoms(List).
Enter Symptom: Stop
List = [].
?- get_symptoms(List).
Enter Symptom: A
Enter Symptom: Stop
List = ["A"].
?- get_symptoms(List).
Enter Symptom: a
Enter Symptom: A
Enter Symptom: A line with some spaces
Enter Symptom: Notice that a period is not needed at the end
Enter Symptom: Stop
List = ["a", "A", "A line with some spaces", "Notice that a period is not needed at the end"].
How do I make the Head "Symptoms" and only add the user input to the Tail?
You want to make the user input the head and have the following entries as the tail. The trick for this example is to put the list constructor |/2 after the recursive call, e.g.
get_symptoms(Symptoms0), % Recursive call
Symptoms = [Response|Symptoms0] % List constructor
Secondly, when I change "stop" to "Done" the program no longer stops?
Since Done starts with a capital letter it is a Prolog variable which is causing the problem. stop starts with a lower case letter and is an atom so works as expected with the compare.
If I want to use a capital word, how would I do that?
You can use read/1 which requires the user to input "" when entering the value, e.g.
?- read(X).
|: "Hello".
X = "Hello".
but read/1 reads a term so requires the user to not only add the double quotes but end with a period. Using read_string/5 allows the user to enter data as they would expect. The input will be read and stored as a string. If the data is then to be converted there are predicates that operate on strings

Try something like this:
get_input( Rs ) :-
get_input( [], Rs )
.
get_input( Ss , Rs ) :-
writeln('Enter Element:'),
read( S ),
dif( S , stop ),
!,
get_input( [S|Ss] , Rs )
.
get_input( Rs, Rs ).

Related

Does `cin` produce a newline automatically?

Let's consider the following code:
#include<iostream>
int main()
{
std::cout<<"First-";
std::cout <<"-Second:";
int i;
std::cin>>i;
std::cout<<"Third in a new line.";
while(1){}
}
The output when value 4 is given to i is:
First--Second:4
Third in a newline
cout doesn't print any newline. But after I input any value(4) for i a newline is printed. There could be two possible reasons for this:
The Enter key I press after typing a numerical value for i is printed as a newline.
cin automatically generates a newline.
Although the first reason seems more reasonable but the reason, I am thinking 2nd reason could also be true, is because after Third is printed when I press Enter no new line is printed even the program continue to run because of while(1)--which means the console window doesn't print a newline when Enter key is pressed. So it seems like cin automatically prints a newline.
So, why is the newline being generated after I give input to cin? Does cin automatically prints a newline?
The number and newline you entered is printed by the console software. cin won't print anything in my understanding.
Try giving some input via redirect or pipe, and I guess you will see no new line printed.
For example:
$ echo 4 | ./a.out
First--Second:Third in a new line.
where $ is the prompt and echo 4 | ./a.out(Enter) is your input.
Check this out: http://ideone.com/tBj1uS
You can see there that input and output are separated.
stdin:
1
2
stdout:
First--Second:Third in a new line.
Which means, that the newline is produced by the Enter key and is a part of the input, not the output.
If someone will have the same problem, I was able to solve it like this:
string ans1;
getline(cin, ans1);
ans1.erase(remove(ans1.begin(), ans1.end(), '\n'),
ans1.end());
int ans1int = atoi(ans1.c_str());
Basically, it works by deleting all the newline characters in the string, and then ,aking it integer or whatever else you need. Also you will need algorithm library for it
It's not that elegant, but hey, it works!

Need better regex to test for "a" but not "ax"

I use the following regex in SSRS to test for a particular column name in a parameter:
=IIf(InStr(Join(Parameters!ColumnNames.Value, ","), "x"), False, True)
This will hide a column on a report if it is not one of the chosen columns. This works just fine if there is not another column called "xy". The string being tested may be "z,x,w", in which case the test works fine; but it may also be "z,xy,w", in which case it will find "x" and display both "x" and "xy".
I tried checking for "x," which only works if "x" is not the last character of the string. I need to know the syntax to check for both "x," OR "x as the last piece of the string". Unfortunately "x" can have any length. The basic problem is I do not know how to use an OR in the IIF statement.
I tried the most obvious ways and kept getting errors. Using "\b" also does not work because there are no spaces in the string (so word boundaries are not applicable).
What you can do is add the delimiter to your check, so that way you're checking the exact string only and not any that just include it:
=IIf
(InStr("," & Join(Parameters!ColumnNames.Value, ",") & ",", ",x,") > 0
, False
, True)
So this will catch x but not xy.
One thing to note:
I have added a check to see of InStr > 0, as this returns an integer and not a boolean.
You want to match a specific column name in an array of column names but do this on a single line to include in the IIF statement.
Based on the last technique suggested in How can I quickly determine if a string exists within an array? your code would need to be.
=IIf((UBound(Filter(Parameters!ColumnNames.Value, "x", True, compare)) > -1), False, True)
It doesn't look like there is an actual Regex anywhere?

Prolog: Adding elements to list through read/1

I am trying to add user input to a list with add_read_list/2 until the word "end." is encountered. This is how the output is supposed to look:
add_read_list(Resultlist, [a,b]).
|: c.
|: d.
|: e.
|: f.
|: end.
Resultlist = [f,e,d,c,a,b].
This is how far I have come:
add_read_list(Resultlist,Entrylist) :-
read(end), append([], Entrylist, Resultlist).
add_read_list(Resultlist, Entrylist) :-
read(Input), append([Input], Entrylist, X),
add_read_list(Resultlist, X).
But this way every second input gets skipped:
add_read_list(Resultlist, [a,b]).
|: c.
|: d.
|: e.
|: f.
|: end.
Resultlist = [f,d,a,b].
What am I doing wrong?
drop the first clause, and use the simple 'if/then/else' construct:
add_read_list(Resultlist, Entrylist) :-
read(Input),
( Input = end
-> reverse(Resultlist, Entrylist)
; add_read_list(Resultlist, [Input|Entrylist])
).
instead of appending each item read, 'cons' it, and reverse the full list when done (well, simply unify to get the list in LIFO, as seems required. i.e. instead of reverse(Resultlist, Entrylist), Resultlist = Entrylist)
The actual error is read(end). This will only succeed, if the term read in is end. Otherwise it fails.
But I do have a lot of reservation to tell you this at all, since nobody every does this is Prolog. Here are the actual things that would need improvement.
The first, is to use end_of_file in place of end, because this is automatically generated at the end of a file, plus you can write it yourself, too.
The second is the way how to handle this. You need to read and then process the term read in:
... read(X), ( X == end_of_file -> ... ; /* whatever */ ... ), ....
However, please do reconsider your entire task. There is a single reason why this could be needed: When you are processing a Prolog file. But this you get cheaper and less error prone by saying [file].
So better design your data to fit into Prolog terms.

[c++]while(cin.get(str,size).get())... why infinit looping,rather than quit if i give a blank line

it's a c++ question.
char str[10];
while(cin.get(str,10).get())
...
cin.clear();
i hope when i give just the enter key, the while loop would end due to that the cin.get(str,size) would fail encountering the blank line. but when I add a .get() behind aim to read up the following \n, the while loop just keep looping when i give a blank line?
is it that the .get() causes the judgement true override the cin.get(str,size)'s false?
cin.get(str,10) Extracts characters from the stream and stores them in str as a c-string, until either 9 characters have been extracted or the delimiting character is encountered, not "gets 10 and fails if it cant, because the line ended."
This will basically never "fail" until you get to the end of file.
You will have to capture the line and test its length separately (probably not in the same expression)

Find 3 or more repeating charaters in a string

I'm trying to find any occurrences of a character repeating more than 2 times in a user entered string. I have this, but it doesn't go into the if statement.
password = asDFwe23df333
s = re.compile('((\w)\2{2,})')
m = s.search(password)
if m:
print ("Password cannot contain 3 or more of the same characters in a row\n")
sys.exit(0)
You need to prefix your regex with the letter 'r', like so:
s = re.compile(r'((\w)\2{2,})')
If you don't do that, then you'll have to double up on all your backslashes since Python normally treats backlashes like an escape character in its normal strings. Since that makes regexes even harder to read then they normally are, most regexes in Python include that prefix.
Also, in your included code your password isn't in quotes, but I'm assuming it has quotes in your code.
Can't you simply go through the whole string and everytime you found a character equal to the previous, you incremented a counter, till it reached the value of 3? If the character was different from the previous, it would only be a matter of setting the counter back to 0.
EDIT:
Or, you can use:
s = 'aaabbb'
re.findall(r'((\w)\2{2,})', s)
And check if the list returned by the second line has any elements.