Prolog: Reverse function of string_to_list - prolog

I know the Prolog-builtin "string_to_list". Now i need to reverse its functionality.
?- string_to_list('a*1+2', L).
L = [97, 42, 49, 43, 50].
How can i reverse this? Is there a builtin function?
Anything that does what "desiredfunction" does, would be a great help.
?- desiredfunction([97, 42, 49, 43, 50], R).
R = 'a*1+2'.
Thank you.

string_to_list/2 is deprecated in favor of string_codes/2.
The predicate is bidirectional, meaning that you can plug in a list, and get a string back on the other side.
string_codes(R, [97, 42, 49, 43, 50])
Better yet, use atom_codes/2, which is also bidirectional, and is more widely supported among Prolog implementations:
atom_codes(R, [97, 42, 49, 43, 50])
This produces
a*1+2

Related

Restricting variables to a domain in z3

Restricting BitVec's to the values of a list doesn't work as I expected, at least not by using in.
from z3 import *
s = Solver()
lst = [7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 35, 37, 38, 41, 42, 44, 49, 50]
BV = [BitVec(f"bv1{j + 1}", 8) for j in range(11)]
lst_as_domain = [bv in lst for bv in BV]
s.add(lst_as_domain)
print(lst_as_domain) #[False, False, False, False, False, False, False, False, False, False, False]
print(s.check()) #unsat
If I use list comprehension as follows, it works.
from z3 import *
s = Solver()
lst = [7, 11, 13, 14, 19, 21, 22, 25, 26, 28, 35, 37, 38, 41, 42, 44, 49, 50]
BV = [BitVec(f"bv{j + 1}", 8) for j in range(11)]
lst_as_domain = [Or([B[k] == li for li in lst]) for k in range(11)]
s.add(lst_as_domain)
print(lst_as_domain) #[Or(bv1 == 7, bv1 == 11,... ,bv1 == 50), Or(bv2 == 7,...)..]
print(s.check()) #sat
print(s.model()) #[bv4 = 42, bv7 = 37,..., bv11 = 41]
Why doesn't the first code yield my desired restriction? How can I use in to assert a domain to variables, or is there a short command to achieve this?
Python's built-in in method does not do what you think it should do on symbolic expressions. This is a problem of the very loosely-typed nature of the z3 python bindings: Instead of doing symbolic equality, it checks for object equality, and always get False as an answer which you found when you printed lst_as_domain.
The solution is what you already found. Do not use in. For reuse purposes, I'd define a function like:
def member(x, es):
return Or([x == e for e in es])
And then use it as:
lst_as_domain = [member(bv, lst) for bv in BV]
which will do the right thing and is "close" enough to what you wanted to write in the first place.
This is a common gotcha for the Python bindings, unfortunately. While it tries to make symbolic z3 expressions look and behave like Python expressions themselves, it doesn't always work due to limitations in Python and the z3-Python API itself; which makes it error-prone to use unless you're very careful about what methods are overloaded to work on symbolic expressions and which are not.
Aside: Unfortunately there's no easy way to tell which constructs will work on symbolic values out-of-the-box. You have to study how they're implemented internally. Rule-of-thumb: Anything that Python doesn't allow you to overload, you cannot use on symbolic values. But that's not an easy test, admittedly.

prolog - not a function warning

I have this Prolog program where I want to match players with players with the same level (newbie, intermediate, or expert) and server:
player(player29, 408, 183, europe).
player(player30, 462, 97, north-america).
player(player31, 25, 22, asia).
player(player32, 481, 248, asia).
player(player33, 111, 37, asia).
player(player34, 424, 359, north-america).
player(player35, 381, 358, asia).
player(player36, 231, 159, africa).
player(player37, 31, 20, africa).
player(player38, 22, 21, africa).
player(player39, 144, 35, oceania).
player(player40, 30, 25, asia).
player(player41, 221, 112, south-america).
player(player42, 344, 292, africa).
player(player43, 183, 148, asia).
player(player44, 62, 40, africa).
player(player45, 281, 23, north-america).
player(player46, 308, 173, south-america).
player(player47, 127, 125, asia).
player(player48, 441, 393, south-america).
player(player49, 213, 48, oceania).
player(player50, 343, 145, africa).
winrate(X):-player(X, T, W, _); (W/T) * 100.
newbie(X):-winrate(X) < 40.
intermediate(X):-winrate(X) >=40; winrate(X) < 80.
expert(X):-winrate(X) > 80.
However, I get a warning saying "Arithmetic: 'winrate(_G1082)' is not a function" when I compile it. Can someone explain to me what that means?
If I could nominate a misconception in Prolog for greatest all-time beginner stumbling block, it would be this: there is no such thing as a return value in Prolog. So the problem comes down to this definition:
winrate(X) :- player(X, T, W, _); (W/T) * 100.
If you type just that into Prolog, you'll get a mysterious looking warning message:
Warning: user://1:9:
Singleton variable in branch: T
Singleton variable in branch: W
I suspect you think that clause says "Look up T and W for player X and return W/T * 100." What Prolog actually thinks you said there is "Look up T and W for player X, or something over something times one hundred <awkward pause>" which is not particularly meaningful. When you ask winrate(player47), Prolog will stand in the corner with its hands in its pockets and say "um, true?"
The correction is this:
winrate(X, Rate) :- player(X, T, W, _), Rate is (W/T) * 100.
You have the exact same problem a little further down in newbie/1 et. al.: winrate(X) < 40 does not have intrinsic meaning in Prolog, because there is no "return value" in Prolog. The corrected expression is winrate(X, WinRate), WinRate < 40.
Note that there is nothing special about the last argument in Prolog. It's common for predicates with one-way semantics to use the last arguments for results, but it isn't really a law and Prolog is not enforcing anything there.
Pay close attention to singleton variable errors. Nothing meaningful happens in Prolog without variables appearing more than once, so if you get this error and you immediately replace the named variables with _, does your clause still seem to have enough information to do its work? If not, you have almost certainly missed something or are confused about Prolog's semantics. Believe me, I learned this one from experience.

How to use variables in Prolog query shell?

I know that I can use variables in Prolog shell (something like using '$' character, I think...but I don't remember...)
If I execute the following query it seems to work fine:
?- leggiFile('dataggare.txt', ListaTesto), tokenizzaLista(ListaTesto, TokenizedList, 1).
ListaTesto = [68, 117, 114, 97, 110, 116, 101, 32, 105|...],
TokenizedList = [t(1, [68, 117, 114, 97, 110, 116, 101]), t(-1, [32]), t(2, [105, 108]), t(-1, [32]), t(3, [77, 101, 100|...]), t(-1, [44]), t(-1, [32]), t(4, [...|...]), t(..., ...)|...]
But if I try to execute the two query leggiFile/2 and tokenizzaLista/2 separately, in this way go into error:
?- leggiFile('dataggare.txt', ListaTesto).
ListaTesto = [68, 117, 114, 97, 110, 116, 101, 32, 105|...].
?- tokenizzaLista($ListaTesto, TokenizedList, 1).
ERROR: variable `ListaTesto' does not exist
Why? it seems to me very strange. What am I missing?
?- open('uty.pl',read,S).
S = <stream>(0x236d4d0).
?- read($S,K).
K = (:-module(uty, [atoi//2, cache_file/2, cache_path/4, call_nth/2, cat/2, count_solutions/2, ... / ...|...])).
?- read($S,K).
K = (:-reexport(nb_uty, [ (<<)/2, (>>)/2, ++ / 2, (**)/2])).
...
but I'm not sure if garbage collection could disturb...
Documentation states
Bindings resulting from the successful execution of a top-level goal are asserted in a database if they are not too large.

How can I sort numbers as though they were words?

Ruby's Array#sort will, by default, sort numbers like this, in order of their value:
[11, 12, 13, 112, 113, 124, 125, 127]
I'd like to sort an array of numbers like this, as though they were words being alphabetized:
[11, 112, 113, 12, 124, 125, 127, 13]
How can I do this? (Ultimately, I want to do this with Hash keys, so if you want to answer that way instead, that's fine.) Also, is there a name for this type of sort?
You are all crqzy ))) I have a such solution:
a.sort_by &:to_s
Well, one way is to convert all of the values to strings, then convert them back.
a = [11, 12, 13, 112, 113, 124, 125, 127]
a = a.map(&:to_s).sort.map(&:to_i)
p a # => [11, 112, 113, 12, 124, 125, 127, 13]
You can pass in a block to sort that accepts two arguments and returns the result of your own custom-defined comparison function. The example should speak for itself, but should you have any questions, feel free to ask.
a = [11, 112, 113, 12, 124, 125, 127, 13]
new_a = a.sort do |x,y|
"%{x}" <=> "%{y}"
end
puts new_a
A note: I suspect that the reason you're looking for this sort of solution is because the objects you want sorted are not Integers at heart. It might be worthwhile and semantically more pleasing to subclass Integer. Although it will obviously make instantiation harder, it feels more correct, at least to me.

Two stars in a Prolog list

what are the two stars in a list?
[53, 5, 1, 53, 97, 115, 53, 50, 52, 121, 55, 56, 55, 97, 4, 1, 98, **]
I tried searching but no success.
The stars indicate that the term contains itself, e.g.
?- X = f(X).
X = f(**).
?- L = [53, L].
L = [53, **].
This is the case at least in older versions of SWI-Prolog.
See also https://lists.iai.uni-bonn.de/pipermail/swi-prolog/2009/001707.html.

Resources