I did not understand how to find the right solution for this problem:
The following lists of real numbers are supplied at the input (there
may be others, but you need to decide with this sample):
list1 = [1,1,1,1,2]
list2 = [1,1,1,2,1]
list3 = [1,1,2,1,1]
list4 = [10,10,10,10,20]
list5 = [1,1,1,-2,1]
list6 = [1,1,-2,1,1]
list7 = [1,251,2,53,-12]
list8 = [1,1,1,1,-2]
list9 = [-1,-1,-1,-1,-2]
list10= [1,0,-32,1,4]
You need to compare list1 with all the others and identify the most
similar (display the coefficient of coincidence from 0 to 1 or the
difference coefficient).
The problem is that the correct result should be list2, as the most similar one.
I tried algorithms from Euclidean geometry and also used chatGPT to help, but it also did not cope with this task, no matter what algorithms I use, the program produces the wrong list (not list2).
Related
I have a list 'a' in Prolog.
a = [].
I have to insert to 'a' another list 'b'
b = [bottle].
The final result has to be like this:
a = [[bottle]].
The build-in function append/3 seems to only concatenate two lists.
append([item1,item2],[item3,item4],Ans) gives us Ans = [item1,item2,item3,item4] but I need
Ans = [[1,2,3],[4,5,6]].`
Can you please help me with this task, I am completely noob in prolog.
I'm working on lists of "People" objects in Haskell, and I was wondering if there was any difference in performance between head$dropWhile and head$filter to find the first person with a given name. The two options and a snip of the datatype would be:
datatype Person = Person { name :: String
, otherStuff :: StuffTypesAboutPerson }
findPerson :: String -> [Person] -> Person
findPerson n = head $ dropWhile (\p -> name p /= n)
findPerson n = head $ filter (\p -> name p == n)
My thought was, filter would have to compare the full length of n to the full length of every name until it finds the first one. I would think dropWhile would only need to compare the strings until the first non-matching Char. However, I know there is a ton of magic in Haskell, especially GHC. I would prefer to use the filter version, because I think it's more straight-forward to read. However, I was wondering if there actually is any performance difference? Even if it's negligible, I'm also interested from a curiosity standpoint at this point.
Edit: I know I also need to protect from errors with Maybe, etc, but I left that out to simplify the code example.
There are several approaches to the problem
findPerson n = head $ dropWhile (\p -> name p /= n)
findPerson n = head $ filter (\p -> name p == n)
findPerson n = fromJust $ find (\p -> name p == n)
The question also points out two facts:
when x,y are equal strings, == needs to compare all the characters
when x,y are different strings, /= only needs to compare until the first different character
This is correct, but does not consider the other cases
when x,y are equal strings, /= needs to compare all the characters
when x,y are different strings, == only needs to compare until the first different character
So, between == and /= there is no performance winner. We can expect that, at most, one of them will perform an additional not w.r.t. the other one.
Also, all the three implementations of findPerson mentioned above, essentially perform the same steps. Given xs :: [Person], they will all scan xs until a matching name is found, and no more. On all the persons before the match, the name will be compared against n, and this comparison will stop at the first different character (no matter what comparison we use above). The matching person will have their name compared completely with n (again, in all cases).
Hence, the approaches are expected to run in the same time. There might be a very small difference between them, but it could be so small that it would be hard to detect. You can try to experiment with criterion and see what happens, if you wish.
We have N sets of integers A1, A2, A3 ... An. Find an algorithm that returns a list containg one element from each of the sets, with the property that the difference between the largest and the smallest element in the list is minimal
Example:
IN: A1 = [0,4,9], A2 = [2,6,11], A3 = [3,8,13], A4 = [7,12]
OUT: [9,6,8,7]
I have an idea about this exercise, first we need sort all the elements on one list(every element need to be assigned to its set), so with that input we get this:
[[0,1],[2,2],[3,3],[4,1],[6,2],[7,4],[8,3],[9,1],[11,2],[12,4],[13,3]]
later on we create all possible list and find this one with the difference between smallest and largest element, and return correct out like this: [9,6,8,7]
I am newbie in ocaml so I have some questions about coding this stuff:
Can I create a function with N(infinite amount of) arguments?
Should I create a new type, like list of pair to realize assumptions?
Sorry for my bad english, hope you will understand what I wanted to express.
This answer is about the algorithmic part, not the OCaml code.
You might want to implement your proposed solution first, to have a working one and to compare its results with an improved solution, which I now write about.
Here is a hint about how to improve the algorithmic part. Consider sorting all sets, not only the first one. Now, the list of all minimum elements from all sets is a candidate to the output.
To consider other candidate output, how can you move from there?
I'm just going to answer your questions, rather than comment on your proposed solution. (But I think you'll have to work on it a little more before you're done.)
You can write a function that takes a list of lists. This is pretty much the same
as allowing an arbitrary number of arguments. But really it just has one argument
(like all functions in OCaml).
You can just use built-in types like lists and tuples, you don't need to create or
declare them explicitly.
Here's an example function that takes a list of lists and combines them into one big long list:
let rec concat lists =
match lists with
| [] -> []
| head :: tail -> head # concat tail
Here is the routine you described in the question to get you started. Note that
I did not pay any attention to efficiency. Also added the reverse apply (pipe)
operator for clarity.
let test_set = [[0;4;9];[2;6;11];[3;8;13]; [7;12]]
let (|>) g f = f g
let linearize sets =
let open List in sets
|> mapi (fun i e -> e |> map (fun x -> (x, i+1) ))
|> flatten |> sort (fun (e1,_) (e2, _) -> compare e1 e2)
let sorted = linearize test_set
Your approach does not sound very efficient, with an n number of sets, each with x_i elments, your sorted list will have (n * x_i) elements, and the number of sub-lists you can generate out of that would be: (n * x_i)! (factorial)
I'd like to propose a different approach, but you'll have to work out the details:
Tag (index) each element with it's set identifier (like you have done).
Sort each set individually.
Build the exact opposite to that of your desired result!
Optimize!
I hope you can figure out steps 3, 4 on your own... :)
Alright so I am coding a parser for arithmetic equations. I get the input in a list, e.g. "10+20" = [49,48,43,50,48] and then I convert all the digits to there corresponding numbers e.g. [49,48,43,50,48] = [1,0,43,2,0] and from there I want to put integers > 10 back together.
Converting from ascii -> digits I use a maplist and number_codes to convert.
One approach I had was to just traverse the list and if it's 0-9 store it in a variable and then check the next number, 0-9 append it to the other variable and so on until I hit an operator. I can't seem to simply append digits as it were. Here's my current code.
expression(L) :-
maplist(chars, L, Ls).
chars(C, N) :-
(
C >= "0", "9" >= C -> number_codes(N, [C]);
N is C
).
Not sure if there's a simple way to add to my code (as far as I know, maplist only gives back a list of equal length to the list passed in but I could be mistaken).
Any help is appreciated :)
Yes, maplist only 'gives back' a list of equal length. Moreover, maplist applies a predicate only to one element (basically it's context-free). Therefore, it is not possible to do what you want (combine digits between operators to a single number) with maplist and you would have to write the recursion yourself.
However, you can do something way easier than all this converting back and forth:
expression(L, E):-
string_to_atom(L,A),
atom_to_term(A,E,[]).
Which works like this:
2 ?- expression("1+2",E).
E = 1+2.
3 ?- expression("1+2",E), X is E.
E = 1+2, X = 3.
4 ?- expression("1+2",E), X+Y = E.
E = 1+2, X = 1, Y = 2.
5 ?- expression("1+2+3",E), X+Y = E.
E = 1+2+3, X = 1+2, Y = 3.
Naturally, if you want a list with all the numbers involved you will have to do something recursive but this is kinda trivial imho.
If however you still want to do the converting, I suggest checking Definite Clause Grammars; it will simplify the task a lot.
I answered some time ago with an expression parser.
It will show you how to use DCG for practical tasks, and I hope you will appreciate the generality and simplicity of such approach.
Just a library predicate is required from SWI-Prolog, number//1, easily implemented in Sicstus. Let me know if you need more help on that.
I am working on a SML programming assingment for class and stuck on a question. The question is:
"Write an ML function that uses map, foldr, or foldl to compute the intersection of a nonempty list of sets.Here you may assume that sets are denoted as lists. For this problem, you may use auxilary named functions (e.g., isMember). Hint: A nonempty list of sets contains at least one set."
This is what I have so far can anyone point me in the right direction I am fairly new to SML?
fun member(x,[]) = false
| member(x,L) =
if x=hd(L) then true
else member(x,tl(L));
fun intersect(L1,L2) = if tl(L1) = [] then L1
else if member(hd(L1),L2) = true then L1
else intersect(tl(L1),L2);
fun combine(L1) = if tl(L1) = [] then hd(L1)
else
foldr intersect [] L1;
What I want the code to do is start off by executing the combine function with a lists of lists. It checks if there is only one list (i.e. tl(L1) = []) and if it is true then just print the first list. If its false I want to call the foldr function that then calls the intersect function. In theory during the foldr function I want it to check the first list and second list and only keep what values are the same, then check the next list to those kept values and keeping doing this until it has checked every list. After that is done I want it to print each value that was in each list (i.e. intersection of sets).
I know my member function works and the combine function does what its supposed to do, my QUESTION is, what is wrong with the intersection function and can someone explain what the intersection should be doing?
I obviously don't want the straight up answer, that's not what I am here for. I need help to get on track for the right answer.
Your member and combine functions seem fine, but you need to think through the intersect function more carefully. For starters, if L1 is an empty list, it rases an exception, because tl doesn't operate on empty lists. Think about the three cases you need to worry about:
L1 is nil
hd(L1) is in L2
hd(L1) is not in L2
Figure out what you need to do in each case and go from there.
Here is my working answer!
fun member(x,[]) = false
| member(x,L) =
if x=hd(L) then true
else member(x,tl(L));
fun intersect([],[]) = []
| intersect(L1,[]) = []
| intersect(L1,L2) = if member(hd(L2), L1) then hd(L2)::intersect(L1, tl(L2))
else intersect(L1, tl(L2));
fun combine(L1) = if L1 = [] then []
else if tl(L1) = [] then hd(L1)
else foldr intersect (hd(L1)) (tl(L1));
Here are some test cases ran.
combine([[1,2],[1,3],[1,4]]);
val it = [1] : int list
combine([[1,2,3],[1,8,9,3],[1,4,3,8,9]]);
val it = [1,3] : int list
combine([[1,2,3,8,9],[1,8,9,3],[1,4,3,8,9]]);
val it = [1,3,8,9] : int list