sort values of an orddict - sorting

In order to extract the values (records) of an orddict as a sorted list, tried this:
-module(test).
-compile(export_all).
-record(node, {name="", cost=0}).
test() ->
List = orddict:append("A",#node{name="A",cost=1},
orddict:append("B",#node{name="B",cost=2},
orddict:new())),
lists:sort(fun({_,A},{_,B}) -> A#node.cost =< B#node.cost end,
orddict:to_list(List)).
The sort fails with exception error: {badrecord,node}.
What would be the correct syntax?
Solved:
The correct insertion method is orddict:store/2 instead of orddict:append/2. Then the pattern {_,A} matches for the comparison function.

The correct syntax is:
lists:sort(fun({_,[A]},{_,[B]}) -> A#node.cost =< B#node.cost end,
orddict:to_list(List)).
I not found note about this in documentation,but you can look in source code of module.
As #Pascal write in comments the reason is that orddict:append/3 is a function provided to append a value to an existing Key/Value pair where Value must be a list. In the use case, the key doesn't exist, so the pair is created and the Value append to an empty list.
Btw, you always can print and compare real and expected result.
io:format("~p~n",[orddict:to_list(List)])
For your example that is:
[{"A",[{node,"A",1}]},{"B",[{node,"B",2}]}]

Related

SWI-Prolog Replacing an Atom value by another value

I am a newbie to SWI-Prolog and am facing an issue. So I have these Atoms named GUID1 and GUID2. Initially suppose GUID1 = 'ABC'. After following statement:
gensym(GUID1,GUID2)
GUID2 becomes 'ABC1'. Now I need to concatenate this ABC1 with prefix say 'X', the result by concatenate is received in new Atom say NGUID2. I used
atom_concat(P, GUID2, NGUID2),
P has 'X' as the value.
For now, NGUID2 is successfully bound to 'XABC1'. But For some reason I want this 'XABC1' value to bind to GUID2 as otherwise, it will complicate my other work. Basically I want to reassign GUID2 to value of NGUID2.
Edit 1: I tried b_setval(GUID2, NGUID2) but, it is not updating GUID2. So I'm still stuck.
Edit 2: So as per one of the comments I will specify why I want to do this.
Predicate definition
This is the original implementation which I need to modify. And When I call the predicate with following call.
Calling
The Clone_ID in calling predicate gets bound to the GUID value +1,+2,+3... Eg if GUID value is ABC then Clone_ID will become ABC1 for first call, ABC2 for second call and so on. But Now I want to append a prefix X to Each new value of Clone_ID, so it should be something like XABC1, XABC2, ... and so on. How should I modify the function definition in-order to do so.

Z3 enumsort update

Is it possible to update an enumerated sort by adding (or removing) a symbol to it? What I would like to do is to add a new value to the list of symbols (see below) even after a variable, say "X", is created from that sort.
EnumSort eSort = con.mkEnumSort(name,symbols);
SetSort eSetSort = con.mkSetSort(eSort);
If I create a new enumerated sort and get a value "v" then I get an error "domain sort and parameter do not match" for the expression v \in X (membership).
There isn't a way to change sorts.
You could create a single enumeration sort and add various
range constraints on sets created over the enumeration sort.

Prolog Undefined Procedure

I'm trying to to get a list of three items with their relevant information based on a collection of information:
product(I):-
I = [_,_,_,_], %Type,Brand,Category,Value
cheaper(item(apple,_,_),item(_,kay,_,_),I),
cheaper(item(bar,_,_,_),item(_,_,fruit,_),I),
member(item(_,kay,_,2),I),
member(item(apple,granny,_,_),I),
member(item(bar,_,chocolate,_),I),
/* Below not given */
member(item(cracker,_,_,_),I),
member(item(_,_,biscuit,_),I),
member(item(_,_,_,4),I),
member(item(_,_,_,5),I).
cheaper(X,Y,H) :- %Used to determine the item values
item(X,_,_,A),
item(Y,_,_,B),
A<B.
When I try running it I encounter an error:
?- product(I).
ERROR: cheaper/3: Undefined procedure: item/4
Exception: (8) item(item(apple, _G3604, _G3605), _G3651, _G3652, _G3653) ?
I understand that item isn't a procedure, however what can I used for checking the value for apple against the value for bar?
First, the obvious note, you're calling cheaper wrong once:
cheaper(item(apple,_,_),item(_,kay,_,_),I),
↑
Only three values, not four.
If item isn't a procedure, you mustn't call it, but use destructuring.
Also you want those items you're checking with cheaper to be part of the list, right? If so, you'll have to check that. And you can use unification to extract the values that you need:
cheaper(X,Y,I) :-
member(X,I),
member(Y,I),
[item(_,_,_,A),item(_,_,_,B)] = [X,Y],
A<B.
Now you'll get some errors regarding not instantiated argument. That's because you are checking not (yet) set variables if they are greater than each other. To avoid this, move the cheaper/3 calls to the end of your clause body:
product(I):-
I = [_,_,_,_], %Type,Brand,Category,Value
member(item(_,kay,_,2),I),
member(item(_,_,_,4),I),
member(item(_,_,_,5),I),
member(item(apple,granny,_,_),I),
member(item(bar,_,chocolate,_),I),
/* Below not given */
member(item(cracker,_,_,_),I),
member(item(_,_,biscuit,_),I),
cheaper(item(apple,_,_,_),item(_,kay,_,_),I), % note the 4th argument
cheaper(item(bar,_,_,_),item(_,_,fruit,_),I).
With this, you'll get one solution and then it fails with an error. This is, because you only give three values for the price slot and you have four items and prolog will check A > 2.
Sorry, in my other answer I didn't look for what the poster was trying to achieve and I think that this is better than a complete reedit. (glorious SO mods let me know if I'm wrong)

mathematica: PadRight[] and \[PlusMinus]

Is there any way that
PadRight[a \[PlusMinus] b,2,""]
Returns
{a \[PlusMinus] b,""}
Instead of
a \[PlusMinus] b \[PlusMinus] ""
?
I believe that i need to somehow deactivate the operator properties of [PlusMinus].
Why do i need this?
I'm creating a program to display tables with physical quantities. To me, that means tables with entries like
(value of a) [PlusMinus] (uncertainty of a)
When i have several columns with different heights, i'm stuffing the shorter ones with "", so i can use Transpose the numeric part of the table.
If the column has more than one entrie, there's no problem:
PadRight[{a \[PlusMinus] b,c \[PlusMinus] d},4,""]
gives what i want:
{a \[PlusMinus] b,c \[PlusMinus] d,"",""}
It is when the column has only one entrie that my problem appears.
This is the code that constructs the body stuffed with "":
If[tested[Sbody],1,
body = PadRight[body, {Length[a], Max[Map[Length, body]]
With
tested[a__] :=
If[Length[DeleteDuplicates[Map[Dimensions, {a}]]] != 1, False,
True];
, a function that discovers if is arguments have the same dimension
and
a={Quantity1,Quantity2,...}
Where the quantities are the one's that i want on my table.
Thanks
First you need to be aware of that any expression in Mathematica is in the form of Head[Body]
where body may be empty, a single expression or a sequence of expressions separated by commas
Length operate on expressions, not necessarily lists
so
Length[PlusMinus[a,b]]
returns 2 since the body of the expression contains to expressions (atoms in this case) that are a and b
Read the documentation on PadRight. The second argument define the final length of the expression
so
PadRight[{a,b},4,c] results with a list of length 4 with the last two elements equal to
PadRight[{a,b},2,c] results with the original list since it is already of length 2
Therefore
PadRight[PlusMinus[a,b],2,anything] just returns the same PlusMinus[a,b] unchanged since it is already of length 2
so, youר first example is wrong. You are not able to get a result with head List using PadRight when you try to pad to an expression with head PlusMinus
There is no problem of executing
PadRight[PlusMinus[a,b],3,""]
but the result looks funny (at best) and logically meaningless, but if this is what you wanted in the first place you get it, and following my explanations above you can figure out why
HTH
best
yehuda

itration behaviour when list length = 1

I'm quite new to python and am having issues with for loop behaviour. In my code I'm reading config from a file using configobj. The contents of the config file are variable and that is where I'm seeing issues.
Here's my test code:
if webconf.has_key(group):
scenario_list = webconf[group]['Scenarios']['names']
for scenario in scenario_list:
print "Scenario name = %s\n" % scenario
The "scenario_list" variable will contain any number of strings. When 'names' has multiple elements "scenario" is set to the value of each element, which is fine. When "names" has only 1 element then the loop iterates over each character of the first entry, breaking my code.
So, how do I get the for loop simply to return the value of the entry in "scenario_list" when list length is 1?
Thankyou in advance for any advice offered.
Are you using tuples rather than lists?
aTuple = (1,2,3)
aList = [1,2,3]
The big difference between tuples and lists are that tuples are immutable and lists are mutable. That is, with a list you may change the element of a list, or even add and remove elements.
The problem that you are likely encountering is related to a concept called tuple unpacking.
aList = [0] # aList is now [0]
notATuple = (0) # notATuple is now 0
# there was exactly one element in the tuple, so it was unpacked in the variable
aTuple = (0,) # aTuple is now (0,) - a tuple with one element
# the comma indicates that you wish that the tuple should not be unpacked
The only other problem I think of is that you are not putting the scenario string in a list or tuple when you have only one scenario. Python treats strings like lists (well, more like tuples) of characters. As such, if you iterate over a string you get the individual characters (the behaviour you experienced). Hence, you must put your scenario string in a list (or tuple) if want to iterate over your one string, and not its characters. Had you not been using strings you would have seen a runtime error.

Resources