Find the smallest subsequence of k distinct elements in a list - arrays

I am super new to sml. I am trying to write a simple code that takes an array of 5 positions with certain numbers and returns the length of the smallest subarray that contains all numbers. However I am getting many error messages that I cannot find in Google. Can anyone help me? The code is the following
fun Min x y = if x>y then return y else return x
local
val a = Array.array (3,0)
val cordela = Array.array(5,0)
val k=0
val front=0
val tail=0
val min=5
update(cordela,0,1)
update(cordela,1,3)
update(cordela,2,3)
update(cordela,3,2)
update(cordela,4,1)
in
fun loop front =
case k>3 of
if sub(a,sub(cordela,front)-1) = 0 then k=k+1 else()
update(a,sub(cordela,front)-1),sub(a,sub(cordela,front)-1)+1)
front = front +1
|
min= Min (front-tail) min
if sub(a,sub(cordela,front)-1) = 0 then k=k-1 else()
update(a,sub(cordela,front)-1),sub(a,sub(cordela,front)-1)-1)
tail=tail+1
if 5>front then loop front+1 else min
end
The error messages that I get are:
pl2.sml:16.13-16.15 Error: syntax error: replacing OF with LBRACKET
pl2.sml:18.36 Error: syntax error: inserting LPAREN
pl2.sml:20.4 Error: syntax error: replacing BAR with EQUALOP
pl2.sml:22.5 Error: syntax error: inserting LPAREN
pl2.sml:26.4 Error: syntax error: inserting LPAREN
pl2.sml:27.2 Error: syntax error found at END
Edit: I am trying to write this code in sml. It is written in c++
while(front < N){
if( k < K ){
if ( e[cordela[front]-1] == 0 ) k += 1;
e[cordela[front]-1] +=1;
front++ ;
}
else{
min = MIN(front - tail ,min);
if ( e[cordela[tail]-1] ==1 ) k -= 1;
e[cordela[tail]-1] -= 1;
tail++;
}
}

As John Coleman says, SML/NJ will not give very helpful error messages. You could try and install Moscow ML instead, since it gives better error messages. Unfortunately, there are some things wrong with this code at a syntactic level that makes it difficult for the compiler to give a meaningful error. Here are some hints to get the syntax right so that you can focus on the algorithm problems:
Don't use local, use let.
Match each ( with a ); you have too many )s.
Declare fun loop ... = ... inside let and in.
Once you've done that, a template for the function that solves your problem could look like:
fun smallest_subarray (needles : Array.array, haystack : Array.array) =
let
val ... = ...
fun loop ... = ...
in
if Array.length needles > Array.length haystack
then ...
else loop ...
end
What if there's no solution to the problem, what will the function return? ~1? NONE?
If you're trying to convert a C++ program to SML, try and include the function part in such a way that it's obvious what identifiers are arguments to the function, and try to name them logically; I have no idea what cordela, e and k are, or if N is a function of the size of the input array, or a constant.
Since an idiomatic solution in SML uses recursion (the function calling itself) rather than iteration (while), you are dealing with both a non-trivial algorithm problem and another paradigm. Try instead to solve a similar, but simpler problem where the algorithm is more trivial and apply the recursion paradigm.
For example, try and write a function that finds the position of an element in a sorted array using binary search:
fun find x arr =
let
fun loop ... = ...
in
loop ...
end
The loop function would take the search bounds (e.g. i and j) as argument and return either SOME i if x is found at position i, or NONE. You could extend this problem in the direction of your original problem by then trying to write a function that determines if an input array, needles, occurs in another input array, haystack, in the order given in needles. You could first assume that needles and haystack are sorted, and then assume that they're not.

Related

OCaml matching in a sorting algorithm 0(n^2)

I have tried several things. Can I simply not match with less than?
The exception is redundant, to enable the matching loop. I can imagine all sorts of things are wrong and this bit of code. It would be nice if the vague less-than-you-less-than-me concept worked.
I admit I am frustrated. Why do I get an error at j < k every time, no matter where I improve or edit? Is that simply against the rules?
I was just looking at Array Length > Array Length as my while condition, that will have to change. Also, none of the Array Sorting methods seem to me to work in the smallest upwards routine as I understand the 0(n^2).
Can this code implement Array.for_all as a sorting algorithm?
UPDATE
let i = Array.length arr in
let sort (arr : array) (j : int) (k : int) =
Array.make n x = unsorted(arr : array) (n : int) (x : int)
while i > 0
match j < k with
| true -> a.(n) <- j
| false -> failwith (Printf.sprintf "Exception Found (%d)" i)
i - 1
;;
That was a lot of questions.
Thank you.
UPDATE:
I appreciate the help very much.
I know I need two arrays, not one. The finished code should read an array, and then give an array back. So, when k points to a smallest j the purpose of the algorithm is to kick j out of the first array, from wherever it it is, put it into the second array, and append every j after that one into the second array. The job is done when the first array is empty.
I see plenty of information about lists out there but not much about arrays. How can I remove the j_n-th element of an array?
This is a nice looking example of recursion used to search and delete an element from a list, can that work in an array?
Thank you again
The match in OCaml is restricted (in essence) to matching a value (an expression) against a set of structured constants that are known at compile time. If you want to test something like whether j < k you should just use an if expression, even if it's not as exotic and powerful seeming.
There are many other problems with your code, but this seems to answer your main question.
You can use an expression in a when clause to further constrain when a pattern matches. Simple example:
let f x =
match x with
| _ when x < 5 -> true
| _ -> false
In this trivial case, an if is of course better, but it can be useful in more complicated pattern matching with lots of options.
You'll have a lot of problems with your code but to answer your question, there are 3 ways I can see to do what you want to do:
match j < k with
| true -> a.(n) <- j
| false -> failwith (Printf.sprintf "Exception Found (%d)" i)
match j with
| _ when j < k -> a.(n) <- j
| _ -> failwith (Printf.sprintf "Exception Found (%d)" i)
if j < k
then a.(n) <- j
else failwith (Printf.sprintf "Exception Found (%d)" i)
The latter being the better. The only thing you need to remember is that pattern matching is done on patterns, it looks at what the values are, not their relations to other values. You can match an int with 1, 3 or 127 but not match this int with another one or compare it with another one.
On a side note, here are some problems in your code and some answers to your questions:
sort takes an array, a j, a k and a i but then
You use Array.make by checking if it's equal to unsorted (x = f is a boolean comparison unless you write let x = f in ...). It looks like you're trying to define an internal function but it's unclear how you're making it
if you want to define a randomly sorted array, you could just write Array.init 100 (fun _ -> Random.int 100)
you're clearly trying to sort your array between i and n (while a.(i) > a.(n) do ... done but then you're checking on j that is a parameter of your function and that never changes
Array.for_all checks that a predicate is true for every value in the array. If you want to apply a function with a different return type to your array you can either use Array.map:
map f a applies function f to all the elements of a, and builds an array with the results returned by f: [| f a.(0); f a.(1); ...; f a.(length a - 1) |].
or Array.fold_{left|right}:
fold_left f init a computes f (... (f (f init a.(0)) a.(1)) ...) a.(n-1), where n is the length of the array a.
fold_right f a init computes f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...)), where n is the length of the array a.
As for the sorting functions, what makes you think they won't run in O(n^2)? You can look at the way they're implemented here

Why do I keep getting an error that array indices must be positive?

It says the index in position 1 of the diff function must be a positive integer or a logical value which is it so why am I getting this error? I'm trying to implement the basic Euler method in MATLAB
y=zeros(1,6);
h=0;
x(1)= 0;
y(1)= 0;
i=1;
diff(y,x)= x+y
while h<=1
y(i+1)=y(i) + h*f(x(i))
h=h+0.2;
i=i+1;
end
Edit: Changed it to the code below but it still raises the same error in the line y(i+1)=...
y=zeros(1,6);
x=zeros(1,6);
h=0;
i=1;
g=x+y;
while h<=1
y(i+1)=y(i) + h*g(x(i),y(i));
h=h+0.2;
i=i+1;
end
Approach: I would recommend defining an anonymous function
diffh =#(x,y) x + y; % define this prior to use
to use later inside the loop.
Then changing one line
y(ii+1)=y(ii) + h*diffh(x(ii),y(ii));
should work. I've added the "h" to the end as a convention to remind me this is an anonymous function (see note at end).
% MATLAB R2019a
y = zeros(1,6);
x = zeros(1,6);
h=0;
ii=1;
diffh =#(x,y) x + y;
while h <= 1
y(ii+1)=y(ii) + h*diffh(x(ii),y(ii));
x(ii+1) = x(ii)+h;
h=h+0.2;
ii=ii+1;
end
Side note: I've also changed the index i to ii by convention (though MATLAB doesn't require this). Unless you overwrite their values, both i and j default as the sqrt(-1). You can absolutely use them as indices without issue (provided you don't later need complex or imaginary numbers). To ensure this never becomes an issue, many people just use ii and jj as a convention to preserve the default values.
Note that diff is a MATLAB function itself.
Using i as an index is mostly not a good idea in Matlab, because i is also imaginary number. Perhaps another name could solve the problem.

Why does my while loop not terminate in this functional language?

I'm trying to build a standard ML program using both imperative and functional concepts, and write the contents to a file. But my while loop doesn't seem to terminate and instead prints the same value continuously.
fun writeImage image filename =
let val ap = TextIO.openOut filename
val (w,h) = size image
val row = ref 0
val stringToWrite = "";
in
while !row < h do
TextIO.output(ap,"A");
row := !row + 1;
TextIO.closeOut ap
end;
If I remove the first line after the while loop, the loop terminates. But if I include TextIO.output(ap,"A");, it doesn't. Why is this the case?
Let's write your program with correct indentation, and then it becomes clear where the mistake is:
...
while !row < h do
TextIO.output(ap,"A");
row := !row + 1;
TextIO.closeOut ap
...
You loop forever because the increment is outside of the body of the loop.
You intended to write this:
...
while !row < h do (
TextIO.output(ap,"A");
row := !row + 1
);
TextIO.closeOut ap
...
right?
I have long made a study of how people come to make mistakes when programming. I am curious to know how you came to make this mistake. If you believed that ; binds stronger than while then why did you believe that the TextIO.closeOut ap was after the loop? Surely if your belief was that the ; binds the increment to the loop then the ; should bind it to the loop as well. Did you perhaps think that ML is a language like Python, where the looping constructs use the whitespace as a guide to the extent of the body?
What are your beliefs about ; in ML more generally? Do you think of ; as a statement terminator, as it is in C-like languages? Or do you think of it as an infix sequencing operation on side-effecting expressions?
What was your thought process here, and how could the tooling have made it easier for you to solve your problem without having to ask for help?

Find longest suffix of string in given array

Given a string and array of strings find the longest suffix of string in array.
for example
string = google.com.tr
array = tr, nic.tr, gov.nic.tr, org.tr, com.tr
returns com.tr
I have tried to use binary search with specific comparator, but failed.
C-code would be welcome.
Edit:
I should have said that im looking for a solution where i can do as much work as i can in preparation step (when i only have a array of suffixes, and i can sort it in every way possible, build any data-structure around it etc..), and than for given string find its suffix in this array as fast as possible. Also i know that i can build a trie out of this array, and probably this will give me best performance possible, BUT im very lazy and keeping a trie in raw C in huge peace of tangled enterprise code is no fun at all. So some binsearch-like approach will be very welcome.
Assuming constant time addressing of characters within strings this problem is isomorphic to finding the largest prefix.
Let i = 0.
Let S = null
Let c = prefix[i]
Remove strings a from A if a[i] != c and if A. Replace S with a if a.Length == i + 1.
Increment i.
Go to step 3.
Is that what you're looking for?
Example:
prefix = rt.moc.elgoog
array = rt.moc, rt.org, rt.cin.vof, rt.cin, rt
Pass 0: prefix[0] is 'r' and array[j][0] == 'r' for all j so nothing is removed from the array. i + 1 -> 0 + 1 -> 1 is our target length, but none of the strings have a length of 1, so S remains null.
Pass 1: prefix[1] is 't' and array[j][1] == 'r' for all j so nothing is removed from the array. However there is a string that has length 2, so S becomes rt.
Pass 2: prefix[2] is '.' and array[j][2] == '.' for the remaining strings so nothing changes.
Pass 3: prefix[3] is 'm' and array[j][3] != 'm' for rt.org, rt.cin.vof, and rt.cin so those strings are removed.
etc.
Another naïve, pseudo-answer.
Set boolean "found" to false. While "found" is false, iterate over the array comparing the source string to the strings in the array. If there's a match, set "found" to true and break. If there's no match, use something like strchr() to get to the segment of the string following the first period. Iterate over the array again. Continue until there's a match, or until the last segment of the source string has been compared to all the strings in the array and failed to match.
Not very efficient....
Naive, pseudo-answer:
Sort array of suffixes by length (yes, there may be strings of same length, which is a problem with the question you are asking I think)
Iterate over array and see if suffix is in given string
If it is, exit the loop because you are done! If not, continue.
Alternatively, you could skip the sorting and just iterate, assigning the biggestString if the currentString is bigger than the biggestString that has matched.
Edit 0:
Maybe you could improve this by looking at your array before hand and considering "minimal" elements that need to be checked.
For instance, if .com appears in 20 members you could just check .com against the given string to potentially eliminate 20 candidates.
Edit 1:
On second thought, in order to compare elements in the array you will need to use a string comparison. My feeling is that any gain you get out of an attempt at optimizing the list of strings for comparison might be negated by the expense of comparing them before doing so, if that makes sense. Would appreciate if a CS type could correct me here...
If your array of strings is something along the following:
char string[STRINGS][MAX_STRING_LENGTH];
string[0]="google.com.tr";
string[1]="nic.tr";
etc, then you can simply do this:
int x, max = 0;
for (x = 0; x < STRINGS; x++) {
if (strlen(string[x]) > max) {
max = strlen(string[x]);
}
}
x = 0;
while(true) {
if (string[max][x] == ".") {
GOTO out;
}
x++;
}
out:
char output[MAX_STRING_LENGTH];
int y = 0;
while (string[max][x] != NULL) {
output[y++] = string[++x];
}
(The above code may not actually work (errors, etc.), but you should get the general idea.
Why don't you use suffix arrays ? It works when you have large number of suffixes.
Complexity, O(n(logn)^2), there are O(nlogn) versions too.
Implementation in c here. You can also try googling suffix arrays.

MATLAB min(array) gives index exceeds array dimensions [duplicate]

This question already has an answer here:
sum(Array) says index exceeds matrix dimensions [duplicate]
(1 answer)
Closed 3 years ago.
I am trying to find the minimum value of a function of two variables, and then find the value of the variables.
My method is to iterate the function through several values of the variables and then use the min function to find the lowest value.
minval = -10;
maxval = 10;
n = 1;
for x = minval:maxval
for y = minval:maxval
f(n) = abs(x-1)+abs(y-1)+abs(x-3)+abs(y-5)+abs(x-8)+abs(y-3);
n=n+1;
end
end
f(n) = abs(x-1)+abs(y-1)+abs(x-3)+abs(y-5)+abs(x-8)+abs(y-3);
fmin = min(f)
The problem is with the last line:
fmin = min(f)
I am getting the error
??? Index exceeds matrix dimensions.
Error in ==> Lab2 at 65
fmin = min(f)
Why is this? Any help is greatly appreciated.
Don't define a variable named min. Try this:
which min
What does it tell you?
Note that functions in MATLAB can be overloaded by creating variables with the same name. When you do so, you prevent the function from being accessed by MATLAB. This is RARELY a good idea, so don't do it. The solution is
clear min
So you will delete that variable you have created. Of course, if there was something important in that variable, stuff it somewhere else first.
It does indeed look like you have declared a variable called min and so Matlab now treats it like a variable and not a function so it thinks you are trying to index the variable min with the vector f.
But just a comment on your code, leaving off whatever f(442) is you could achieve the same thing in a much more matlabesque fashion without loops like this:
minval = -10;
maxval = 10;
X = minval:maxval;
Y = X;
[xx, yy] = meshgrid(X, Y);
F = abs(xx-1) + abs(yy-1) + abs(xx-3) + abs(yy-5) +abs(xx-8) + abs(yy-3);
Your f is now equivalent to F(:)' (without the final value...), prove it to yourself like this: sum(f(1:end-1) == F(:)')
F as a matrix probably makes more sense than f as a flat vector anyway and you can find the min of F like this: min(F(:))
This code runs perfectly when I plug it into my version of Matlab.
If the error is occuring on line 65, then there must be something else going on in your program. Try and turn this part of your program into a function, so that it won't be impacted by everything else that you're working on.

Resources