Output any string input with Prolog - io

Checking to see if it's possible to format a string reliably with base model prolog(no modules). I have the following code that I thought would work but doesn't:
hello(_) :-
write('\nEnter Name: '),
read(Name),
format('\nThe name you entered is: ~s', [Name]).
This throws the error if the user entered Bob. but works if the user entered "Bob". or 'Bob'.
ERROR: format/2: Illegal argument to format sequence ~s: _G7118
I have also tried replacing the format with writeq like:
hello(_) :-
write('\nEnter Name: '),
read(Name),
writeq(Name).
Which doesn't thrown an error but does just end up printing _L143 instead of Bob

(Too long for a comment)
Don't use read like this, as #lurker explains, it is not for entering "strings" or "text" or answers to questions altogether. Before even going down this road, ask yourself: "Why?"
The Prolog top level is your interactive command line prompt. It is not like in C or any other compiled language where you need to actually make your interpreter.
So, your hello/1 could look like this:
hello(Name) :-
format("~w~n", [Name]).
You still need to say hello("Bob") or hello('Bob') from the prompt, of course.
If you want to make your own interpreter on top of the Prolog top level, this is another thing altogether.

As other have said, read/1 reads only valid Prolog syntax. To read an arbitrary line of text using standard Prolog primitives, you would have to read the input character by character:
read_line(Cs) :-
get_code(C),
( C == 0'\n -> Cs = [] % end of line
; C == -1 -> Cs = [] % end of input
; Cs = [C|Cs1], read_line(Cs1)
).
As you are using SWI-Prolog, indicated by your use of format/2 and the (deleted by others) SWI-Prolog tag, you can also use
read_line(String) :-
current_input(Input),
read_string(Input, "\n", "\r", End, String).
Other systems have the same or similar predicates, but they are not standardized.

Related

How can I print "\n" using exec()?

ab = open("bonj.txt","w")
exec(f'''print("Hi I'm Mark\n", file=ab)
print("\tToday I'm tired", file=ab)
''')
ab.close()
I would absolutely need to use exec() to print some informations on a txt doc. The problem is that when I use exec(), I lost the possibility of put newlines or tabs on my text, and I dont understand why, could you help me ?
This is the error message that I receive : "SyntaxError: EOL while scanning string literal"
You just need to escape \n and \t properly
ab = open("bonj.txt","w")
exec(f'''print("Hi I'm Mark\\n", file=ab)
print("\\tToday I'm tired", file=ab)
''')
ab.close()
You need to prevent python from interpreting the \n early.
This can be done by specifying the string as a raw string, using the r prefix:
ab = open("bonj.txt","w")
exec(rf'''print("Hi I'm Mark\n", file=ab)
print("\tToday I'm tired", file=ab)
''')
ab.close()
Anyway, using exec is odd there, you would rather try to see if you can write your code as something like:
lines = ["Hi I'm Mark\n", "\tToday I'm tired"]
with open("bonj.txt", "w") as f:
f.write("\n".join(lines))
Note that you need to use "\n".join to obtain the same result as with print because print adds a newline by default (see its end="\n" argument).
Also, when handling files, using the context manager syntax (with open ...) is good practice.

How do I get the computer to seperate a conjoined string into seperate items on a list depending on what it detects?

This is a follow up from a question I asked yesterday which I got brilliant responses for but now I have more problems :P
(How do I get python to detect a right brace, and put a space after that?)
Say I have this string that's in a txt document which I make Python read
!0->{100}!1o^{72}->{30}o^{72}->{30}o^{72}->{30}o^{72}->{30}o^{72}->{30}
I want to seperate this conjoined string into individual components that can be indexed after detecting a certain symbol.
If it detects !0, it's considered as one index.
If it detects ->{100}, that is also considered as another part of the list.
It seperates all of them into different parts until the computer prints out:
!0, ->{100}, !1, o^{72}, ->{30}
From yesterdays code, I tried a plethora of things.
I tried this technique which separates anything with '}' perfectly but has a hard time separating !0
text = "(->{200}o^{90}->{200}o^{90}->{200}o^{90}!0->{200}!1o^{90})" #this is an example string
my_string = ""
for character in text:
my_string += character
if character == "}":
my_string+= "," #up until this point, Guimonte's code perfectly splits "}"
elif character == "0": #here is where I tried to get it to detect !0. it splits that, but places ',' on all zeroes
my_string+= ","
print(my_string)
The output:
(->{20,0,},o^{90,},->{20,0,},o^{90,},->{20,0,},o^{90,},!0,->{20,0,},!1o^{90,},)
I want the out put to insead be:
(->{200}, o^{90}, ->{200}, o^{90}, ->{200}, o^{90}, !0, ->{200}, !1, o^{90})
It seperates !0 but it also messes with the other symbols.
I'm starting to approach a check mate scenario. Is there anyway I can get it to split !0 and !1 as well as the right brace?

How to filter only text in a line?

I have many lines like these:
_ÙÓ´Immediate Transformation With Vee_ÙÓ´
‰ÛÏThe Real Pernell Stacks‰Û
I want to get something like this:
Immediate Transformation With Vee
The Real Pernell Stacks
I tried this:
for t in test:
t.isalpha()
but characters like this Ó count as well
So I also thought that I can create a list of English words, a space and punctuation marks and delete all the elements from the line that are not in this list, but I do not think that this is the right option, since the line can contain not only English words and that's fine.
Using Regex.
Ex:
import re
data = """_ÙÓ´Immediate Transformation With Vee_ÙÓ´
‰ÛÏThe Real Pernell Stacks‰Û"""
for line in data.splitlines(keepends=False):
print(re.sub(r"[^A-Za-z\s]", "", line))
Output:
Immediate Transformation With Vee
The Real Pernell Stacks
use re
result = ' '.join(re.split(r'[^A-Za-z]', s))

print(f"...:")-statement too long - break it into multiple lines without messing up the format

I have a console program with formatted output. to always get the same length of the printout, I have a rather complex formatted print output.
print(f"\n{WHITE_BG}{64*'-'}")
print(f"\nDirektvergleich{9*' '}{RED}{players[0].name}{4*' '}{GREEN}vs.{4*' '}{RED}{players[1].name}{CLEAR}\n")
print(f"""{15*'~'}{' '}{YELLOW}Gesamt{CLEAR}:{' '}{players[0].name}{' '}{GREEN}{int(player1_direct_wins)}{(int(4-len(player1_direct_wins)))*' '}-{(int(4-len(player1_direct_losses)))*' '}{int(player1_direct_losses)}{CLEAR}{' '}{players[1].name}{' '}{(28-len(players[0].name)-len(players[1].name))*'~'}\n""")
print(f"""{15*'~'}{' '}{YELLOW}Trend{CLEAR}:{' '}{players[0].name}{' '}{GREEN}{int(player1_trend_wins)}{(int(4-len(player1_trend_wins)))*' '}-{(int(4-len(player1_trend_losses)))*' '}{int(player1_trend_losses)}{CLEAR}{' '}{players[1].name}{' '}{(28-len(players[0].name)-len(players[1].name))*'~'}""")
print(f"\n{WHITE_BG}{64*'-'}")
This leads to the following output in my windows cmd
For readibility purpose, I tried to make the print over multiple lines, therefore I found on stackoverflow the idea to start with triple quotes. But when I cut this print(f"...") statement in the middle, I mess up my formatting.
Example:
print(f"\n{WHITE_BG}{64*'-'}") #als String einspeisen?!
print(f"\nDirektvergleich{9*' '}{RED}{players[0].name}{4*' '}{GREEN}vs.{4*' '}{RED}{players[1].name}{CLEAR}\n")
print(f"""{15*'~'}{' '}{YELLOW}Gesamt{CLEAR}:{' '}{players[0].name}{' '}{GREEN}{int(player1_direct_wins)}{(int(4-len(player1_direct_wins)))*' '}-
{(int(4-len(player1_direct_losses)))*' '}{int(player1_direct_losses)}{CLEAR}{' '}{players[1].name}{' '}{(28-len(players[0].name)-len(players[1].name))*'~'}\n""")
print(f"""{15*'~'}{' '}{YELLOW}Trend{CLEAR}:{' '}{players[0].name}{' '}{GREEN}{int(player1_trend_wins)}{(int(4-len(player1_trend_wins)))*' '}-
{(int(4-len(player1_trend_losses)))*' '}{int(player1_trend_losses)}{CLEAR}{' '}{players[1].name}{' '}{(28-len(players[0].name)-len(players[1].name))*'~'}""")
print(f"\n{WHITE_BG}{64*'-'}")
leads to...
can anyone point me in the right direction how to format my output in the displayed way, but without having this absurd long line length.
Thank you guys in advance!
Triple quoted strings preserve newline characters, so they are indeed not what you want here. Now when it finds two adjacent strings, the Python parser automagically concatenates them into a single string, i.e.:
s = "foo" "bar"
is equivalent to
s = "foobar"
And this works if you put your strings within parens:
s = ("foo" "bar")
in which case you can put each string on its own line as well:
s = (
"foo"
"bar"
)
This also applies to "fstrings" so what you want is something like:
print((
f"{15*'~'}{' '}{YELLOW}Gesamt{CLEAR}:{' '}{players[0].name}{' '}{GREEN} "
f"{int(player1_direct_wins)}{(int(4-len(player1_direct_wins)))*' '}-"
f"{(int(4-len(player1_direct_losses)))*' '}{int(player1_direct_losses)}"
f"{CLEAR}{' '}{players[1].name}{' '}{(28-len(players[0].name)-"
f"len(players[1].name))*'~'}\n"
))
That being said, I'd rather use intermediate variables than trying to cram such complex expressions in a fstring.

Why does error 'unexpected character after line continuation character' appear here?

Does someone know what is wrong with this section of my code as it seems to cause errors. I'm new to programming so I'm not completely sure what's wrong.
menu = "Be Lenny's Friend?\n"
1. Yes\n\
2. No\n\
answer = int(input(menu))
if answer == 1:
print(" ( ͡° ͜ʖ ͡°): Yayyyy! We are going to be friends!")
elif answer == 2:
reason = input(" ( ͡° ʖ̯ ͡°): Why do you not want to be my friend :(")
Error message:
'unexpected character after line continuation character'
Here you have set the variable as a tuple of a string and... well that’s where things get confusing.
The backslash is a like continuation symbol as in you can then break the line and continue on and it would count as the same line. However what the interpreter sees is n: which makes no sense. That is what it is complaining about.
If you wanted to add a new line to the string itself, you could add the \n at the end of the string.
However, also note that if you printed the string using print in the vanilla form without any other arguments than the Adrianne itself, it will append a new line automatically. So if you do add the \n, it may still not be what you want when you print it out. Parameter can of course be changed in the print function to take care of that.
I'm not sure what you are trying to archive with ,\n\: at the end of the line, but this line of code will remove the syntax error:
menu = "Be Lenny's Friend?"
If you want to archive a new line after the string you need to move "\n" into the string like this:
menu = "Be Lenny's Friend?\n"
Edit:
This should work for you:
menu = "Be Lenny's Friend?\n\t1. Yes\n\t2. No\n"
answer = int(input(menu))
if answer == 1: print(" ( ͡° ͜ʖ ͡°): Yayyyy! We are going to be friends!")
elif answer == 2: reason = input(" ( ͡° ʖ̯ ͡°): Why do you not want to be my friend :(\n")

Resources