Haskell increment the last element of a tuple - list

Hi could you please help me on how to increment the last element of a tuple.
Currently i have this list of tuples
items :: [Grocery]
items = [("Water", "Drink Section", 1),
("Squash", "Drink Section", 1),
("Apple", "Fruit Section", 1),
("Plates", "Disposable Section", 1),
("Plates", "Ceramic Section", 1)]
and what i wanted to do is increment it by 1 every time the item is bought and output the database. currently i have this
sales:: [database] -> String -> String-> [database]
sales db itemName sectionName = []
sales ((item, section, qty): xs) itemName sectionName
| item == itemName && section== sectionName = [(item, section, qty + 1)]
| otherwise = []
im still in the bit of incrementing it and im stuck. please help me i'm still a newbie on this language. thank you!
Edit
its all working now but how do you output the rest of the list? i tried recordSale xs trackArtist trackTitle but when i test it the old record that i incremented gets printed as well instead of getting modified? lets say that i incremented apple what it'll print is this
[("Apple", "Fruit Section", 2),("Water", "Drink Section", 1),("Squash", "Drink Section", 1), ("Apple", "Fruit Section", 1)]
it duplicates the record instead of just adding 1

That's not bad, but lets pretend you're trying to increment "Squash", the second element down in your example list of items. What does sales do? It checks if the first item in the list, Water, equals Squash. Since water doesn't equal squash it hits the otherwise case and returns [].
So all of that seems right up until we got a [] back - lets change the code in otherwise. Obviously we don't want to throw away the entire list, that would be stupid. You should rewrite it to keep the item that was just compared and concatenate it on to the result of sales applied to the rest of the list (xs).
After you get that otherwise branch fixed you're going to notice the entire list after the item you increment is thrown away - I think that one will pop right out at you once you finish this issue.
P.S. Fire the employee that put Squash in the drinking section.

Related

finding member in nested lists netlogo

i'm trying to solve a problem in netlogo that has me stuck for a while now. i've got two lists (of turtles i've collaborated with and of "successful"/"unsuccessful" judgments). the two lists are mapped like so [[(turtle 10) "successful"] [(turtle 11) "unsuccessful"] with the following:
let general-history (map list collaborators my-success)
where the collaborators are the who numbers and my-success is a string (either "successful" or "unsuccessful")
now, i would like to check whether a turtle has, in its general-history list, at least one successful and one unsuccessful collaborator, to be able to proceed. this is where i've gotten to:
ifelse not empty? general-history and member? "successful " last general-history and member? "unsuccessful" last general-history
i know this is wrong because last here implies that i'll be looking only at the last list of general-history (i.e., [] [] [this one]). what i want it to do is assess whether there are at least two lists (one with "successful" as index 1 and one with "unsuccessful" as index 1) in the whole general-history nested list.
would foreach work better here or is it possible to still use member? but with some kind of element + list indexing? thank you very much for the help!
If I have understood your question correctly, you can use map to create a list of all the last items (success or not) and then apply member? to that list. Here is a complete model example that constructs some test data and the applies this approach.
to testme
clear-all
; create some test data
create-turtles 10
let collaborators sort n-of 3 turtles
let list-both (map list collaborators (list "yes" "no" "no"))
print list-both
; check condition
print member? "yes" map last list-both
end

Find String from One List within Another List and Return String Found

I found part of what I was looking for at Matchlists/tables in power query, but I need a bit more.
Using the "Flags only" example provided at Matchlists/tables in power query, I’m comparing two lists, ListA and ListB, to check if ListB’s row content appears in ListA’s row content at all. I can’t do a one-for-one match of both rows’ contents (like with List.Intersect) because the content of a row in ListB might only be part of the content of a row in ListA.
Note that, in the query below, ListB includes “roo”, which is the first three letters in the word room. I would want to know that “roo” is in ListA’s row that has “in my room.”
The "Flags only" example provided by Matchlists/tables in power query already determines that “roo” is part of ListA’s row that has “in my room.” I built on the example to assign “yes,” instead of true when there is such a match between the ListA and ListB.
What I’d like to do is to replace “yes” with the actual value from ListB — the value “roo,” for instance. I tried to simply substitute wordB for “yes” but I got an error that wordB wasn’t recognized.
let
ListA = {"help me rhonda", "in my room", "good vibrations", "god only knows"},
ListB = {"roo", "me", "only"},
contains_word=List.Transform(ListA, (lineA)=>if List.MatchesAny(ListB, (wordB)=>Text.Contains(lineA, wordB)) = true then "yes" else "no")
in
contains_word
The current query results in this:
List
1 yes
2 yes
3 no
4 yes
I want the query results to be:
List
1 roo
2 me
3
4 only
Any idea how to make it so?
(p.s. I'm extremely new to Power Query / M)
Thanks
I would do this way:
let
ListA = {"help me rhonda", "in my room", "good vibrations", "god only knows"},
ListB = {"roo", "me", "only"},
contains_word=List.Transform(ListA, (lineA)=>List.Select(List.Transform(ListB, (wordB)=>if Text.Contains(lineA, wordB) = true then wordB else null), (x)=>x <> null){0}?)
in
contains_word
[edited]
The idea is to use List.Transform twice: inner one changes list B to leave only matching values. Then 1st non-null of latest replaces string from list A (outer List.Tramsform).
Edit: I think you switched the first 2 elements of the result?
You can use the following code:
let
ListA = {"help me rhonda", "in my room", "good vibrations", "god only knows"},
ListB = {"roo", "help", "me", "only"},
TableA = Table.FromList(ListA,null,{"ListA"}),
AddedListBMatches = Table.AddColumn(TableA, "ListBMatches", (x) => List.Select(ListB, each Text.PositionOf(x[ListA], _) >= 0)),
ExtractedValues = Table.TransformColumns(AddedListBMatches, {"ListBMatches", each Text.Combine(List.Transform(_, Text.From), ","), type text}),
Result = ExtractedValues[ListBMatches]
in
Result
The "ExtractedValues" step is the result of pressing the expand button in the header of the "ListBMatches" column and choose Extract Values, comma separated.
This option was added in the January 2017 update.
I added "help" to ListB so the first element of ListA has 2 matches that are both returned.

How to check for exactly two elements in a Prolog list

% The structure of a musical group takes the form
% group(Groupname, Director, Players).
% Players is a (possibly empty) list of musician structures,
% but excludes the musician structure for the Director.
% The Director is also a musician in the group.
% musician structures take the form
% musician(Initials,Surname,
% cv(Years_as_professional,Previous_orchestra,Instrument)).
group(classicalstars,
musician(w,mozart,cv(10,vienna_phil,piano)),
[musician(j,haydn,cv(32,vienna_phil,cello)), musician(j,bach,cv(40,dresden_chamber,viola))]).
group(romantics,
musician(l,beethoven,cv(32,vienna_phil,piano)),
[musician(f,liszt,cv(10,vienna_phil,violin))]).
group(nordicsounds,
musician(e,grieg,cv(50,bergen_phil,piano)),
[ ]).
group(impressions,
musician(g,faure,cv(40,paris_chamber,violin)),
[musician(c,saint-saens,cv(51,paris_chamber,violin)), musician(m,ravel,cv(10,paris_chamber,piano)), musician(o,messiaen,cv(5,paris_chamber,violin))]).
director(X):- group(_,X,_).
musicians(X):- group(_,_,Musicians),
member(X,Musicians).
exists(X):- director(X);
musicians(X).
So I am trying to return the Initial and Surname of the director of the group that has exactly two non-director musicians that play the violin.
So far I have this
hasTwoViolinists(Initial,Surname):- group(_,musician(Initial,Surname,_),[musician(_,_,cv(_,_,violin)),musician(_,_,cv(_,_,violin))]).
Which will only return a group that only has two violinists, which isn't quite what I am looking for
Any help would be appreciated
The first thing I did was to understand the structure of your data and noticed that finding a list of musicians that had exactly two violinist would be the inner most rule so I started on that.
Here is a rule to find exactly two items in a list. It needs to be enhanced to work on the musicians list for the violinist.
find(C,_,C,[]). % True when Count exactly equals Total and list is empty.
% When the head of the list is the item increment the count and do the next item.
find(Total,Item,Count,[H|T]) :-
Item = H,
Count1 is Count + 1,
find(Total,Item,Count1,T).
% When the head of the list is not the item do the next item.
find(Total,Item,Count,[H|T]) :-
Item \= H,
find(Total,Item,Count,T).
% find(2,a,0,[a,b,a,c]).
% true .
%
% find(2,a,0,[a,a,a,c]).
% false.
Note: The hints are spoilers and can be seen by moving your mouse over them.
If the hint has a code solution it is below all of the hints and also as a spoiler so you have to move the mouse to see them.
Hint 1:
Predicates are your friend with Logic Programming.
Hint 2:
Create a Predicate that returns true when a musician is a violinist, and false when a musician is not a violinist.
is_violinist(musician(o, messiaen, cv(5, paris_chamber, violin))).
true.
is_violinist(musician(m, ravel, cv(10, paris_chamber, piano))).
false.
Hint 3:
find used two predicates.
Item = H and
Item \= H
what happens when they are replaced with is_violinist
For reference:
=
\=
\+ is the same as not.
Hint 4:
Now that you can find the musicians with the two violinist how can you use that to find the group?
Hint 5:
Now that you can find the group with the two violinist how can you use that to find the directors initial and surname?
Code for hints. Sorry about the formatting, limits of markdown.
2.
is_violinist(musician(_,_,cv(_,_,violin))).
3.
% True when Count exactly equals Total and list is empty.
find_v(C,C,[]).
% When is_violinist is true for the head of the list increment the count and do the next item.
find_v(Total,Count,[H|T]) :-
is_violinist(H),
Count1 is Count + 1,
find_v(Total,Count1,T).
% When is_violinist is not true for the head of the list do the next item.
find_v(Total,Count,[H|T]) :-
\+ is_violinist(H),
find_v(Total,Count,T).
4.
find_group(Group) :-
group(Group,_,Musicians),
find_v(2,0,Musicians).
5.
find_director(Initial,Surname) :-
group(_,musician(Initial,Surname,_),Musicians),
find_v(2,0,Musicians).

BIRT: Align rows in list element

I'm using the Birt list element to display my data from left to right. (see this question as reference). Eg. List element with a Grid in details and the grid set to inline.
The issue I'm facing now is, that the different rows in the grid are not aligned left to right (probably due to some rows having empty values in some fields). How can I force BIRT to align properly?
EDIT:
This is especially also a problem with longer text that wraps to more than 1 line. The wrapping /multiple lines should be reflected by all list elements in that "row of the output".
Unfortunately, I don't see any chance to accomplish this easily in the generic case - that is, if the number of records is unknown in advance, so you'd need more than one line:
student1 student2 student3
student4 student5
Let's call those line "main lines". One main line can contain up to 3 records. The number 3 may be different in your case, but we can assume it is a constant, since (at least for PDF reports) the paper width is restricted.
A possible solution could work like this:
In your data set, add two columns for each row: MAIN_LINE_NUM and COLUMN_NUM, where the meaning is obvious. For example, this could be done with pure SQL using analytic functions (untested):
select ...,
trunc((row_number() over (order by ...whatever...) - 1) / 3) + 1 as MAIN_LINE_NUM,
mod(row_number() over (order by ...whatever...) - 1), 3) +1 as COLUMN_NUM
from ...
order by ...whatever... -- The order must be the same as above.
Now you know where each record should go.
The next task is to transform the result set into a form where each record looks like this (for the example, think that you have 3 properties STUDENT_ID, NAME, ADDRESS for each student):
MAIN_LINE
STUDENT_ID_1
NAME_1
ADDRESS_1
STUDENT_ID_2
NAME_2
ADDRESS_2
STUDENT_ID_3
NAME_3
ADDRESS_3
You get the picture...
The SQL trick to achieve this is one that one should know.
I'll show this for the STUDENT_ID_1, STUDENT_ID_2 and NAME_1 column as an example:
with my_data as
( ... the query shown above including MAIN_LINE_NUM and COLUMN_NUM ...
)
select MAIN_LINE_NUM,
max(case when COLUMN_NUM=1 then STUDENT_ID else null end) as STUDENT_ID_1,
max(case when COLUMN_NUM=2 then STUDENT_ID else null end) as STUDENT_ID_2,
...
max(case when COLUMN_NUM=1 then NAME else null end) as NAME_1,
...
from my_data
group by MAIN_LINE_NUM
order by MAIN_LINE_NUM
As you see, this is quite clumsy if you need a lot of different columns.
On the other hand, this makes the output a lot easier.
Create a table item for your dat set, with 3 columns (for 1, 2, 3). It's best to not drag the dataset into the layout. Instead, use the "Insert element" context menu.
You need a detail row for each of the columns (STUDENT_ID, NAME, ADDRESS). So, add two more details rows (the default is one detail row).
Add header labels manually, if you like, or remove the header row if you don't need it (which is what I assume).
Remove the footer row, as you probably don't need it.
Drag the columns to the corresponding position in your table.
The table item should look like this now (data items):
+--------------+--------------+-------------+
+ STUDENT_ID_1 | STUDENT_ID_2 | STUDENT_ID3 |
+--------------+--------------+-------------+
+ NAME_1 | NAME_2 | NAME_3 |
+--------------+--------------+-------------+
+ ADDRESS_1 | ADDRESS_2 | ADDRESS_3 |
+--------------+--------------+-------------+
That's it!
This is one of the few examples where BIRT sucks IMHO in comparison to other tools like e.g. Oracle Reports - excuse my Klatchian.

return elements from list of lists - prolog

I have a list of lists that contain titles and scores like : [ [ 'title1',100 ],[ 'title2',200 ],...]. I have to make a predicate that returns the title if I have a certain score. find_title(Score,List,ListOfTitles). Also some scores may be the same that's why I am trying to store it in a List..in case there is more than one titles with the same score.
I tried this :
return_title(Score,List,[H|T]):-
return_title(Score,List,T),
member([X,Score],List),
H=X.
But it doesn't work..any ideas on another implementation?
Think declaratively: Just consider what the predicate should describe. It's a relation between a score, a list of titles and scores and a list of titles matching the score in the first argument. I find it helpful to find descriptive names for predicates, where one can see at once which argument is what. So why not go with something like score_list_titles/3. Then I think about what cases there are to cover in my description. For this relation I see three cases:
score_list_titles(_S,[],[]). % 1: if list is empty titles is empty
score_list_titles(S,[[T,S]|TSs],[T|Ts]) :- % 2: if score matches S, T is in titles
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
score_list_titles(S,[[T,X]|TSs],Ts) :- % 3: if score
dif(S,X), % doesn't match S, T is not in titles
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
Querying this predicate produces the following results: Which titles have a score of 100, 200 and 300 respectively?
?- score_list_titles(100,[['title1',100],['title2',200],['title3',100]],T).
T = [title1,title3] ? ;
no
?- score_list_titles(200,[['title1',100],['title2',200],['title3',100]],T).
T = [title2] ? ;
no
?- score_list_titles(300,[['title1',100],['title2',200],['title3',100]],T).
T = []
What titles are there for what scores?
?- score_list_titles(S,[['title1',100],['title2',200],['title3',100]],T).
S = 100,
T = [title1,title3] ? ;
S = 200,
T = [title2] ? ;
T = [],
dif(S,100),
dif(S,200),
dif(S,100)
You can even express this relation more compactly by using if_/3:
score_list_titles(_S,[],[]).
score_list_titles(S,[[T,X]|TSs],TL) :- % if S=X: T is in titles
if_(S=X, TL=[T|Ts], TL=Ts), % otherwise it isn't
score_list_titles(S,TSs,Ts). % relation must hold for the tails as well
This way the predicate doesn't even leave an unnecessary choice-point open in the case where the first two arguments are ground (= contain no free variables). You can see that if you compare the below queries with the above ones: In the above version of score_list_titles/3 I had to enter ; after the single answer, to get the feedback that there are no further solutions.
?- score_list_titles(100,[['title1',100],['title2',200],['title3',100]],T).
T = [title1,title3]
?- score_list_titles(200,[['title1',100],['title2',200],['title3',100]],T).
T = [title2]
you're doing more complex than needed:
return_title(Score,List,X):-
member([X,Score],List).
then you can use Prolog 'all solutions' builtins, like findall/3, or REPL backtracking (hit ';' after an answer).