Sort an array of arrays in Erlang - arrays

I need to sort arrays but not classical ones. Moreover, in Erlang !
I'm talking about arrays where each element is an array of two integers.
For example :
[ [6,0], [12,1], [5,2], [10,3] ]
I need this array to be sorted in function of the first element of each arrays
Like this :
[ [5,2], [6,0], [10,3], [12,1] ]
First, I succeed with this :
-module(insertSort).
-export([insertion/1,insert/1,insert/2]).
insertion(L) -> lists:foldl(fun insert/2, [], L).
insert([]) -> [].
insert(X,[]) -> [X];
insert([],Y) -> [Y];
insert(X= [X1,_], L= [[H1,_] | _]) when X1 =< H1 -> [X|L];
insert(X,[H|T]) -> [H|insert(X, T)].
Sometimes, arrays are sorted. But I have two examples that gives me two weird cases:
First :
[ [10,3], [5,2], [12,1], [6,0] ]
become :
[[[5,2], [6,0], [10,3], [12,1]]]]
Not bad but I can't work with that weird construction. It seems that I have an array, where there is an array inside, where there is all my two-elements arrays inside.
Second :
[ [5,16], [11,12], [9,8], [16,4] ]
become :
[[[5,16], "\t\b","\v\f",[16,4]]]
Yes, really, with these \t\b..
I'm a beginner in Erlang but I succeed to do a lot of things by myself.
My project is about Shank Algorithm, trying to solve y = a^x mod n where y, a and n are given.
Can you please help me by telling me what is wrong with my insertSort module ?
Thanks a lot, sorry for my english, I tried to do my best.

As I said in my comment, the sort function of the lists library does exactly what you want.
1> lists:sort( [ [6,0], [12,1], [5,2], [10,3] ]).
[[5,2],[6,0],[10,3],[12,1]]
2>

You probably shouldn't write your own sorting function. If lists:sort(List) isn't what you want for your use case, you could sort on only the first element of the sublists like this:
lists:sort(fun ([H1|_],[H2|_]) -> H1 =< H2 end,
List)

I think problem is with line:
insert([],Y) -> [Y];
Y is already a sorted list so it should be returned as it is
insert([],Y) -> Y;
Erlang strings are list of integers so when your list is not really a string but contains code points of your specified encoding, then it is printed in string notation, but it's still a list. List [65,65,67,68] is equal to "ABCD". Try to type that list into your shell, it's just an erlang pretty printing... not accurate sometimes.

Related

Return all possible Cuts of array A If you have defined number of parts M

I am trying to prepare for job interview using codility and i came up with a question which is not codility task for which i don't know to write algorithm that gives solution. I know it sounds like college homework but sadly those days are gone for me and we never had this complex algorithms there so i have no colleague to ask for solution and that is why I am asking you guys here.
I am most comfortable in javascript but any language will do.
Task:
Lets say you have input Array A with with input length N and you have
also input number M which defines how many array cuts you need to
have. The goal is to return all possible cuts.
N/M <= 1
So for example if you have Array A = [1,2,3,4] and M = 2
solution is array L containing arrays
[ [1] [2,3,4] ]
[ [1,2] [3,4] ]
[ [1,2,3] [4] ]
I'm sure that more efficient algorithms for this exist, but I would do something like this.
def findAllCuts(array,length,cuts):
cuts = []
for i in range(0,length-cuts):
cut = array[:i]
subCuts = findAllCuts(array[i:],length-i,cuts-1)
for j in range(len(subCuts)):
cuts.add(cut+subCuts[j])
return cuts
It should go through all the possible first cuts, and recurse over all future cuts given that first cut.
If empty cuts aren't allowed, change the 0 in the 3rd line to a 1, so that the cut must contain at least one element.

MiniZinc join arrays of variables by index

I have a MiniZinc program with 3 arrays of variables of the following form:
array[NbLines] of var Domain: vars1;
array[NbLines, NbRows] of var Domain: vars2;
array[NbLines, NbRows] of var Domain: vars3;
I need to specify my search variable order in the following way, but I did not success to correctly construct my array. There is the MiniZinc like code:
varsOrder = [[vars1[i]] ++ row(vars2, i) ++ row(vars3, i) | i in NbLines]
MiniZinc indicates that arrays are not allowed in array comprehension expressions. How should I do?
Thank you for your help.
As you have noticed, you cannot concatenate arrays like this. What I can think of are two approaches, though the first is not exactly what you want.
1) use array1d(array)
You can flatten matrices (2d arrays) with "array1d" like this:
solve :: int_search(vars1 ++ array1d(vars2) ++ array1d(vars3), first_fail, indomain_min, complete) satisfy;
However, this is not exactly the same as what you write above, but it's way easier than the next approach:
2) Make a master array and insert all the elements in the proper positions.
int: totLen = ...; % the total length of all the arrays
array[1..totLen] of var Domain: all;
You have to do a loop to insert all the elements in the exact position you want in the "all" array. However, I leave this as an exercise. :-)
Then the "all" array can be used in the labeling:
solve :: int_search(all, first_fail, indomain_min, complete) satisfy;

Sort Arrays in Array in Lua

Hi i am quite new to lua and i need to sort an Array in Lua.
So i have following code
local distances = {2,3,1}
table.sort(distances)
now i get
distances[1] -> 1
distances[2] -> 2
distances[3] -> 3
now i need to save some information for my "distances" aswell
something like the following
local distances = {{C1,2},{C2,3},{C3,1}}
now it is impossible to call the sort-function, but i need them sorted.
Is it possible to reach this?
distances[1] -> {C3,1}
distances[2] -> {C2,2}
distances[3] -> {C1,3}
Thanks guys :)
table.sort takes a comparison function as its second argument.
table.sort(distances, function (left, right)
return left[2] < right[2]
end)

Array vs List in Elm

I was suprised to learn that Array and List were two different types in Elm:
Array
List
In my case, I have a List Int of length 2,000,000 and I need about 10,000 of them but I don't know in advance which ten thousand. That will be provided by another list. In pseudo-code:
x = [ 1,1,0,30,...,255,0,1 ]
y = [ 1,4,7,18,36,..., 1334823 , ... 1899876 ]
z = [ y[x[0]], y[x[1]], ... ]
I am using pseudocode because clearly this isn't Elm syntax (it might be legal JavaScript).
Can these array selections be done in List or Array or both?
List is a linked list which provides O(n) lookup time based on index. Getting an element by index requires traversing the list over n nodes. An index lookup function for List isn't available in the core library but you can use the elm-community/list-extra package which provides two functions for lookup (varying by parameter order): !! and getAt.
Array allows for O(log n) index lookup. Index lookups on Array can be done using Array.get. Arrays are represented as Relaxed Radix Balanced Trees.
Both are immutable (all values in Elm are immutable), so you have trade-offs depending on your situation. List is great when you make a lot of changes because you are merely updating linked list pointers, whereas Array is great for speedy lookup but has somewhat poorer performance for modifications, which you'll want to consider if you're making a lot of changes.
Something like this should work:
import Array
import Debug
fromJust : Maybe a -> a
fromJust x = case x of
Just y -> y
Nothing -> Debug.crash "error: fromJust Nothing"
selectFromList : List a -> List Int -> List a
selectFromList els idxs =
let arr = Array.fromList els
in List.map (\i -> fromJust (Array.get i arr)) idxs
It converts the input list to an array for fast indexing, then maps the list of indices to their corresponding values in the array. I took the fromJust function from this StackOverflow question.
Only use Array if you need to use Array.get.
In most cases you should use List because usually you can do everything you need with foldl, map, etc. without having to get items from an index, and List has better performance with these functions.

How to convert vectors to arrays in ECLiPSe (CLP)? (or Prolog)

I have to solve Sudoku puzzles in the format of a vector containing 9 vectors (of length 9 each). Seeing as vectors are linked lists in Prolog, I figured the search would go faster if I transformed the puzzles in a 2D array format first.
Example puzzle:
puzzle(P) :- P =
[[_,_,8,7,_,_,_,_,6],
[4,_,_,_,_,9,_,_,_],
[_,_,_,5,4,6,9,_,_],
[_,_,_,_,_,3,_,5,_],
[_,_,3,_,_,7,6,_,_],
[_,_,_,_,_,_,_,8,9],
[_,7,_,4,_,2,_,_,5],
[8,_,_,9,_,5,_,2,3],
[2,_,9,3,_,8,7,6,_]].
I'm using ECLiPSe CLP to implement a solver. The best I've come up with so far is to write a domain like this:
domain(P):-
dim(P,[9,9]),
P[1..9,1..9] :: 1..9.
and a converter for the puzzle (parameter P is the given puzzle and Sudoku is the new defined grid with the 2D array). But I'm having trouble linking the values from the given initial puzzle to my 2D array.
convertVectorsToArray(Sudoku,P):-
( for(I,1,9),
param(Sudoku,P)
do
( for(J,1,9),
param(Sudoku,P,I)
do
Sudoku[I,J] is P[I,J]
)
).
Before this, I tried using array_list (http://eclipseclp.org/doc/bips/kernel/termmanip/array_list-2.html), but I kept getting type errors. How I did it before:
convertVectorsToArray(Sudoku,P):-
( for(I,1,9),
param(Sudoku,P)
do
( for(J,1,9),
param(Sudoku,P,I)
do
A is Sudoku[I],
array_list(A,P[I])
)
).
When my Sudoku finally outputs the example puzzle P in the following format:
Sudoku = []([](_Var1, _Var2, 8, 7, ..., 6), [](4, ...), ...)
then I'll be happy.
update
I tried again with the array_list; it almost works with the following code:
convertVectorsToArray(Sudoku,P):-
( for(I,1,9),
param(Sudoku,P)
do
X is Sudoku[I],
Y is P[I],
write(I),nl,
write(X),nl,
write(Y),nl,
array_list(X, Y)
).
The writes are there to see how the vectors/arrays look like. For some reason, it stops at the second iteration (instead of 9 times) and outputs the rest of the example puzzle as a vector of vectors. Only the first vector gets assigned correctly.
update2
While I'm sure the answer given by jschimpf is correct, I also figured out my own implementation:
convertVectorsToArray(Sudoku,[],_).
convertVectorsToArray(Sudoku,[Y|Rest],Count):-
X is Sudoku[Count],
array_list(X, Y),
NewCount is Count + 1,
convertVectorsToArray(Sudoku,Rest,NewCount).
Thanks for the added explanation on why it didn't work before though!
The easiest solution is to avoid the conversion altogether by writing your puzzle specification directly as a 2-D array. An ECLiPSe "array" is simply a structure with the functor '[]'/N, so you can write:
puzzle(P) :- P = [](
[](_,_,8,7,_,_,_,_,6),
[](4,_,_,_,_,9,_,_,_),
[](_,_,_,5,4,6,9,_,_),
[](_,_,_,_,_,3,_,5,_),
[](_,_,3,_,_,7,6,_,_),
[](_,_,_,_,_,_,_,8,9),
[](_,7,_,4,_,2,_,_,5),
[](8,_,_,9,_,5,_,2,3),
[](2,_,9,3,_,8,7,6,_)).
You can then use this 2-D array directly as the container for your domain variables:
sudoku(P) :-
puzzle(P),
P[1..9,1..9] :: 1..9,
...
However, if you want to keep your list-of-lists puzzle specification, and convert that to an array-of-arrays format, you can use array_list/2. But since that only works for 1-D arrays, you have to convert the nesting levels individually:
listoflists_to_matrix(Xss, Xzz) :-
% list of lists to list of arrays
( foreach(Xs,Xss), foreach(Xz,Xzs) do
array_list(Xz, Xs)
),
% list of arrays to array of arrays
array_list(Xzz, Xzs).
As for the reason your own code didn't work: this is due to the subscript notation P[I]. This
requires P to be an array (you were using it on lists)
works only in contexts where an arithmetic expression is expected, e.g. the right hand side of is/2, in arithmetic constraints, etc.

Resources