How to change item in a list with sml? - sml

I have a list of tuples, I want to have a function which randomly choose two tuples in this list and then swap this two tuples.
for example, if I have a list as ((0 , 0), (1 , 0), (1 , 1), (1 , 2) ,(2 , 2), (0 , 2)), then, randomly choose two tuples. if (0,0) and (1,0) are chosen, then the return result of this function will be ((1 , 0), (0 , 0), (1 , 1), (1 , 2) ,(2 , 2), (0 , 2)).
I am new to SML, I am struggling in it. there is a psudo-code, I suppose it is not right, anyone can help me with the right one? :
fun permutation(lst:(int*int) list)=
let
val nextInt = Random.randRange (1,List.length(lst))
val r = Random.rand (1,1)
val x1 = nextInt r
val x2 = nextInt r
val temp = sub(lst,r1)
update(lst,r1,sub(lst,r2))
update(lst,r2,temp)
in
lst
end

Something simple you can do is make a helper function that takes two indices and a list, and returns the two tuples at those indices. Something like
fun get_two (i1, i2, xs) =
let
fun aux (_, _, [], _, val1, val2) = (val1, val2)
| aux (i1, i2, x::xs, current_index, val1, val2) =
if i1 = current_index
then aux (i1, i2, xs, current_index + 1, SOME x, val2)
else if i2 = current_index
then aux (i1, i2, xs, current_index + 1, val1, SOME x)
else aux (i1, i2, xs, current_index + 1, val1, val2)
in
aux (i1, i2, xs, 0, NONE, NONE)
end
Then write another function that takes in a list, uses this get_two helper function to find two values and their positions in the list, and produces a new list that is the same as the input list, except with these two values switched.

Related

Show Multiple occurrences of items in a list, sml

I'm trying to show the indices of all multiple occurrences for an element in a list.
in standard ml.
but my code show the empty list :(
this is my code:
fun index(item, xs,ys) =
let
fun index'(m, nil , ys) = (
SOME (ys) )
| index'(m, x::xr , ys) = if x = item then(
(ys # [m]);
index'(m + 1, xr , ys)
)
else index'(m + 1, xr,ys)
in
index'(0, xs , ys)
end;
index(1,[1,2,1,4,5,1],[]);
can you help me?
First things first:
index should take two arguments; the element to look for and the list to look for it in.
The accumulation parameter belongs to the helper function.
It is meaningless to always produce SOME of something and never NONE.
Let's fix these first.
fun index (item, xs) =
let
fun index'(m, nil , ys) = ys
| index'(m, x::xr, ys) = if x = item then(
(ys # [m]);
index'(m + 1, xr , ys)
)
else index'(m + 1, xr,ys)
in
index'(0, xs, [])
end;
Now you don't need to pass the extra accumulator parameter when you use index.
It's also impossible to start with something other than [].
Your next, and main, problem is
(ys # [m]);
index'(m + 1, xr , ys)
which first creates the list ys # [m], immediately throws it away, and then produces as its result index'(m + 1, xr , ys), which is exactly what the else branch does.
That is, the conditional is equivalent to
if x = item
then index'(m + 1, xr, ys)
else index'(m + 1, xr, ys)
and thus, index' is equivalent to
fun index'(m, nil, ys) = ys
| index'(m, x::xr, ys) = index'(m + 1, xr, ys)
Since you always pass the original ys along, and it is [] to start with, the result is always [].
What you need to do is to pass the extended list to the recursion, so it can become the result when the recursion terminates.
Renaming the accumulator ys to make its purpose clearer:
fun index (item, xs) =
let
fun index'(i, nil, accumulator) = accumulator
| index'(i, x::xr, accumulator) = if x = item
then index' (i + 1, xr, accumulator # [i])
else index' (i + 1, xr, accumulator)
in
index'(0, xs, [])
end;
This is inefficient, due to the repeated appending of an element to the back of a list.
It is very common to accumulate in reverse, and correct it when you're done.
(This "feels" inefficient, but it isn't.)
fun index (item, xs) =
let
fun index'(i, nil, accumulator) = List.reverse accumulator
| index'(i, x::xr, accumulator) = if x = item
then index' (i + 1, xr, i::accumulator)
else index' (i + 1, xr, accumulator)
in
index'(0, xs, [])
end;

ML polymorphic function

I am trying to define a polymorphic function sum over the type T, where type T can be int, real or list of type T. The sum for the case of int and real should work as expected. For the case of list of T, it should return the sum of corresponding elements of two lists (the length of the lists should be same).
Examples:
sum (INT 2, INT 3) = INT 5
sum (REAL 2.3, REAL 3.4) = REAL 5.7
sum(L [2, 3, 4], L [3, 4, 5]) = L [5, 7, 9]
sum(L L([2, 3, 4], [2, 3, 4]), L ([3, 4, 5], [3, 4, 5]) = L ([5, 7, 9], [3, 4, 5])
The function which I wrote are as follows:
datatype T = INT of int | REAL of real | L of T list;
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs, L
ys))
| (_,_) => REAL (0.0);
But for the above function I was getting the error:
Constructor applied to the incorrect argument.
expects: _ * [??? list]
but got: _ * [???]
in: :: (sum (x, y), sum (L xs, L ys))
unhandled exception: Fail: compilation aborted: parseAndElaborate reported errors
Hence I changed my code by adding nil as below. As far as I perceived, the reason for the error was the fact that cons operator was trying to concatenate T (INT or REAL) to T (INT or REAL) in the end as (sum (x, y), sum (L xs, L ys)) will eventually get evaluated by recursive call to INT or REAL . Hence I changed my code by adding nil (empty list) in the end
fun sum (x:T, x':T) = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L (x :: xs), L (y :: ys)) => L ((sum (x, y)) :: (sum (L xs,
L ys)) :: nil)
| (_,_) => REAL (0.0);
But for this case, it behaves correctly for INT and REAL but not for the polymorphic list.
It behaves correctly for INT and REAL (as they are simpler to implement). For the list part, I guess there is some problem with the cons operator and am not able to figure out the solution.
The test cases which I executed and their outputs are as follows:
sum (L([INT(1)]), L([INT(3)]));
val it = L [INT 4,L []] : T
sum (L([INT(1),INT(2)]), L([INT(3),INT(4)]));
val it = L [INT 4,L [INT #,L #]] : T
P.S: Please ignore the last case (,) => REAL (0.0) as I will handle the case of type mismatch later.
This seems like a good use-case for mutually recursive functions:
datatype T = INT of int | REAL of real | L of T list
fun sum (x, x') = case (x, x') of
(INT n, INT n') => INT (n + n')
| (REAL n, REAL n') => REAL (n + n')
| (L ns, L ns') => L (sumLists (ns, ns'))
| (_, _) => ? (* mismatching types *)
and sumLists (x::xs, y::ys) = sum (x, y) :: sumLists (xs, ys)
| sumLists ([], []) = []
| sumLists (_, _) = ? (* mismatching lengths *)
Having REAL 0.0 as the result of mismatching types seems like a problem.
For example, why should sum (INT 2, L [INT 3]) be REAL 0.0?
And why should sum (INT 2, REAL 3.0) be REAL 0.0?
Consider either adding an alternate to INT and REAL that has "no value" if that makes sense for your domain, or, probably better, consider changing the sum function to maybe return a sum, if it can meaningfully be computed on all levels of the tree, i.e. val sum : T * T -> T option. It comes down to error handling.
Write tests that describe the intended behavior of your corner cases. In particular, when it comes to summing values that don't have the same type, and summing lists of mismatching length.
Your examples would look like this as tests:
val test1 = sum (L [INT 1], L [INT 3]) = L [INT 4]
val test2 = sum (L [INT 1, INT 2], L [INT 3, INT 4]) = L [INT 4, INT 6]
Except T isn't an equality type because it contains a real, so you need to write your own equality operator that uses an epsilon test (nearlyEqual) when you encounter a real, for example:
fun eqT (INT x, INT y) = x = y
| eqT (REAL x, REAL y) = nearlyEqual(x, y, someEps)
| eqT (L (x::xs), L (y::ys)) = eqT (x, y) andalso eqT (L ys, L xs)
| eqT (L [], L []) = true
| eqT (_, _) = false
Some of your corner cases might look like
val case1 = sum (INT 2, REAL 3.0)
val case2 = sum (INT 2, L [])
val case3 = sum (INT 2, L [INT 3])
val case4 = sum (L [INT 1], L [INT 1, INT 2])
val case5 = sum (L [INT 1], L [INT 1, REAL 2.0])
val case6 = sum (L [], L [L []])

List consisting of each element of another List repeated twice Prolog

I have to write a predicate: double(X,Y) to be true when Y is the list consisting of each element of X
repeated twice (e.g. double([a,b],[a,a,b,b]) is true).
I ended with sth like this:
double([],[]).
double([T],List) :- double([H|T],List).
double([H|T],List) :- count(H, List, 2).
Its working fine for lists like [a,a,b] but it shouldnt... please help.
And i need help with another predicate: repeat(X,Y,N) to be true when Y is the list consisting of each element of X
repeated N times (e.g. repeat([a,b], [a,a,a,b,b,b],3) is true).
double([],[]).
double([I|R],[I,I|RD]) :-
double(R,RD).
Here's how you could realize that "repeat" predicate you suggested in the question:
:- use_module(library(clpfd)).
Based on if_/3 and (=)/3 we define:
each_n_reps([E|Es], N) :-
aux_n_reps(Es, E, 1, N).
aux_n_reps([], _, N, N). % internal auxiliary predicate
aux_n_reps([E|Es], E0, N0, N) :-
if_(E0 = E,
( N0 #< N, N1 #= N0+1 ), % continue current run
( N0 #= N, N1 #= 1 )), % start new run
aux_n_reps(Es, E, N1, N).
Sample queries1 using SICStus Prolog 4.3.2:
?- each_n_reps(Xs, 3).
Xs = [_A,_A,_A]
; Xs = [_A,_A,_A,_B,_B,_B] , dif(_A,_B)
; Xs = [_A,_A,_A,_B,_B,_B,_C,_C,_C], dif(_A,_B), dif(_B,_C)
...
How about fair enumeration?
?- length(Xs, _), each_n_reps(Xs, N).
N = 1, Xs = [_A]
; N = 2, Xs = [_A,_A]
; N = 1, Xs = [_A,_B] , dif(_A,_B)
; N = 3, Xs = [_A,_A,_A]
; N = 1, Xs = [_A,_B,_C] , dif(_A,_B), dif(_B,_C)
; N = 4, Xs = [_A,_A,_A,_A]
; N = 2, Xs = [_A,_A,_B,_B], dif(_A,_B)
; N = 1, Xs = [_A,_B,_C,_D], dif(_A,_B), dif(_B,_C), dif(_C,_D)
...
How can [A,B,C,D,E,F] be split into runs of equal length?
?- each_n_reps([A,B,C,D,E,F], N).
N = 6, A=B , B=C , C=D , D=E , E=F
; N = 3, A=B , B=C , dif(C,D), D=E , E=F
; N = 2, A=B , dif(B,C), C=D , dif(D,E), E=F
; N = 1, dif(A,B), dif(B,C), dif(C,D), dif(D,E), dif(E,F).
Footnote 1: Answers were reformatted to improve readability.
Ok for repeat/3 i have sth like this:
repeat1([],[],0).
repeat1([A|B],[X|T],Y):- repeat1(B,T,Z), Y is 1+Z.
repeat1([A1|B],[X1|T], Z) :- A1\=A, X1\=X, repeat1(B,T,Z).

Haskell list comprehension compilation error

I want to create a function that given two lists (of floats, but could be anything) gives a list with all the combinations of taking two elements from the first list and putting it in the last and all the combinations of the former putting one of the elements from the last (now with more elements) and putting it back on the first.
For every movement it also gives the greatest value that moved (in the second movement only one moves, that is the value). It should all end when the first list is empty (there would be no second movement).
I can't expect anyone to understand that so, examples:
next [1,2,3,4] [] -> [(([1,2], [3,4], 4), ([1,2,3],[4],3)), (([1,2], [3,4], 4), ([1,2,4],[3],4)), (([1,3], [2,4], 4), ([1,2,3],[4],2)), (([1,3], [2,4], 4), ([1,3,4],[2],4)).....
next [1,2] [3,4] -> [(([], [1,2,3,4],2),)], ())
What I have so far:
module Test where
next :: [Float] -> [Float] -> [(([Float],[Float], Float),([Float],[Float], Float))]
next [] _ = []
next (a:b:[]) s
|a>b = [([],a:b:s, a)]
|otherwise = [([],a:b:s, b)]
next d s = [([x,z], i:j:s, j), b | i <- d, j <- d, i < j, x <- d, z <- d, x < z, z /= i, z /= j, x /= z, x /= i, x /= j, b <- (back [x,z] i:j:s)]
where
back d s = [(i:d, [x,z], i) | i <- s, x <- s, z <- s, x < z, z /= i, x /= z]
Compiling that code gives back an error on the first comprehension list at the | character. I'd kind of understand an error in the back function. Why won't that compile?
The comprehension syntax is
[ <expression> | ... ]
For <expression> you have ([x,z], i:j:s, j), b which is syntactically wrong. Did you mean ([x,z], i:j:s, b)?

Bijective function in sml

I would like to define a function that takes an integer n and returns an integer n* such that n and n* are in the same set of integers from 1 to n,and the function must be bijective.
I tried the following
fun bij(n) =
let
val ls = zip(upto (1, n), List.rev(upto (1, n)))
val Tw_2 = fn(a, b) => b
in Tw_2(List.last(ls, n-1)) end;
but unfortunately, it returns 1 for all my values of n. I am really stuck here.
Can anyone give me some ideas on how to implement this?
The behavior of bij must look something like
bij(1) = 3
bij(2) = 2
bij(3) = 1
If I understand your question correctly, an easy solution would be:
fun bij(n, i) = n + 1 - i;
Which can be represented by the following table
i | 1 2 3 ... n-2 n-1 n
bij(n, i) | n n-1 n-2 ... 3 2 1
and which works as expected for numbers between 1 and n. Intuitively a (positive) number i is i steps "to the right of 0" and we map this to a number that is i (actually i - 1) steps "to the left of n".
Maybe you wanted to construct the above table explicitly via lists?
fun upto(m, n) = if n < m then [] else m :: upto(m+1, n);
fun table n = ListPair.zip (upto(1, n), List.rev (upto(1, n)));
Example:
> table 5;
val it = [(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)]: (int * int) list
Then to get the i-th pair of a list xs you could use
List.nth (xs, i-1)
Putting all together
fun bij(n, i) =
let
val table = ListPair.zip (upto(1, n), List.rev (upto(1, n)));
fun snd(x, y) = y;
in snd(List.nth (table, i-1)) end;
Which does the same as the initial function, except in a more complicated way.