number distribution without repeatable numbers - math

we have a problem in which we need to order/distribute the given set/s such that the numbers are not repeatable
here is an example ,say i have 4 sets
{A,A,A,A,A,A}
{B,B}
{C}
{D,D,D}
the resultant should be something like A,D,A,B,A,D,C,A,D,A,B,A
with no repeatable occurrence.
any thoughts,Algorithms..could be appreciated.
EDIT : sorry for not being clear, by occurrence I meant patterns like AA or BB or CC shouldn't
in the resultant it's OK to have ADAD
Thanks
Dee

A moment's consideration yielded this algorithm:
Let A be the symbol repeated the most times.
Let N be the number of occurrences of A.
Let Rest be the concatenation of the remaining symbols, in order.
Let Buckets be a list of length N, where each element Buckets[i] is an array containing a single A.
Iterate over Buckets: for each index i, pop an element from Rest and append it to Buckets[i]. When you reach the end of Buckets, start from the first index again. When you reach the end of Rest, you are done.
The answer is the concatenation of the contents of Buckets.
Your example:
Let A = 'A'.
Let N = 6.
Let Rest = [B, B, C, D, D, D].
Let Buckets = [[A], [A], [A], [A], [A], [A]].
After iterating, Buckets is [[A, B], [A, B], [A, C], [A, D], [A, D], [A, D]]. The output is ABABACADADAD.

Always pick the bucket with the most amount left.
My rusty Matlab skills did this:
generate a random distribution:
symbols = ceil(rand()*10)+1
maxn = ceil(rand()*20)
distribution= [floor(rand(1,symbols)*maxn);(1:symbols)]'
last = -1;
sequence=[]; #output vector
while sum(distribution(:,1))>0 ; #while something is left
distribution= sortrows(distribution); #sort the matrix
if last == distribution(end,2) #pick the one with the one with the second most elements
if a(end-1,1) ==0 #this means there are no fillers left
break
end
last = distribution(end-1,2);
distribution(end-1,1)--;
else #pick the one with the most elements
last = distribution(end,2);
distribution(end,1) --;
endif
sequence(end+1)=last;
end
sequence
rest = distribution'
Note: My symbols are numbers instead of letters.
Edit: Here is some (beautified) output from the script.

Related

How do I check if the path from a node to another has a depth equal to a given one in a graph in OCaml?

First of all, I'm sorry for how I wrote my question.
Anyway, I'm trying to write a function in OCaml that, given a graph, a max depth, a starting node, and another node, returns the list of the nodes that make the path but only if the depth of it is equal to the given one. However, I can't implement the depth part.
This is what I did:
let m = [(1, 2, "A"); (2, 3, "A");
(3, 1, "A"); (2, 4, "B");
(4, 5, "B"); (4, 6, "C");
(6, 3, "C"); (5, 7, "D");
(6, 7, "D")]
let rec vicini n = function
[] -> []
| (x, y, _)::rest ->
if x = n then y :: vicini n rest
else if y = n then x :: vicini n rest
else vicini n rest
exception NotFound
let raggiungi m maxc start goal =
let rec from_node visited n =
if List.mem n visited then raise NotFound
else if n = goal then [n]
else n :: from_list (n :: visited) (vicini n m)
and from_list visited = function
[] -> raise NotFound
| n::rest ->
try from_node visited n
with NotFound -> from_list visited rest
in start :: from_list [] (vicini start m)
I know I have to add another parameter that increases with every recursion and then check if its the same as the given one, but I don't know where
I am not going to solve your homework, but I will try to teach you how to use recursion.
In programming, especially functional programming, we use recursion to express iteration. In an iterative procedure, there are things that change with each step and things that remain the same on each step. An iteration is well-founded if it has an end, i.e., at some point in time, the thing that changes reaches its foundation and stops. The thing that changes on each step, is usually called an induction variable as the tribute to the mathematical induction. In mathematical induction, we take a complex construct and deconstruct it step by step. For example, consider how we induct over a list to understand its length,
let rec length xs = match xs with
| [] -> 0
| _ :: xs -> 1 + length xs
Since the list is defined inductively, i.e., a list is either an empty list [] or a pair of an element x and a list, x :: list called a cons. So to discover how many elements in the list we follow its recursive definition, and deconstruct it step by step until we reach the foundation, which is, in our case, the empty list.
In the example above, our inductive variable was the list and we didn't introduce any variable that will represent the length itself. We used the program stack to store the length of the list, which resulted in an algorithm that consumes memory equivalent to the size of the list to compute its length. Doesn't sound very efficient, so we can try to devise another version that will use a variable passed to the function, which will track the length of the list, let's call it cnt,
let rec length cnt xs = match xs with
| [] -> cnt
| _ :: xs -> length (cnt+1) xs
Notice, how on each step we deconstruct the list and increment the cnt variable. Here, call to the length (cnt+1) xs is the same as you would see in an English-language explanation of an algorithm that will state something like, increment cnt by one, set xs to the tail xs and goto step 1. The only difference with the imperative implementation is that we use arguments of a function and change them on each call, instead of changing them in place.
As the final example, let's devise a function that checks that there's a letter in the first n letters in the word, which is represented as a list of characters. In this function, we have two parameters, both are inductive (note that a natural number is also an inductive type that is defined much like a list, i.e., a number is zero or the successor of a number). Our recursion is also well-founded, in fact, it even has two foundations, the 0 length and the empty list, whatever comes first. It also has a parameter that doesn't change.
let rec has_letter_in_prefix letter length input =
length > 0 && match input with
| [] -> false
| char :: input ->
char = letter || has_letter_in_prefix letter (length-1) input
I hope that this will help you in understanding how to encode iterations with recursion.

how to understand this recursion in SML?

why does hd dates become the oldest one? I just cannot figure out the process
fun oldest(dates : (int * int * int) list) =
if null dates
then NONE
else
let
val d = oldest(tl dates)
in
if isSome d andalso is_older(valOf d, hd dates)
then d
else SOME(hd dates)
end
In my opinion, this is much easier to understand with a small helper function and case analysis by pattern matching.
(My advice is to get comfortable with patterns and case analysis, avoiding conditionals and selector functions. It's much easier to reason about one thing at a time than to remember a whole chain of logic and destructuring.)
Rewriting your code in that manner might give this:
fun oldest_of (d, d') = if is_older (d, d') then d else d'
fun oldest [] = NONE
| oldest (d::ds) = case oldest ds of
NONE => SOME d
| SOME d' => SOME (oldest_of (d, d'))
That is,
If the list is empty, there is no oldest date
Otherwise, find the oldest date in the input's tail;
If there isn't one, the input's first element must be the oldest
Otherwise, pick the oldest of that and the input's first element
Now it's (hopefully) obvious that the NONE case in the recursion can only occur if the tail, ds, is empty - that is, if the input has exactly one element.
Let's lift that out into its own case:
fun oldest [] = NONE
| oldest [d] = SOME d
| oldest (d::ds) = SOME (oldest_of (d, valOf (oldest ds)))
This reads a lot like this definition of what the oldest date is:
If there are no dates, there is no oldest date
If there is only one date, that is the oldest
If there are at least two dates, it is the oldest of the first date and the oldest one of the rest
which doesn't need much inductive thinking.
You can prove it by induction:
In the case of an empty list, oldest will return NONE.
If the list contains an element, we'll go into the else branch, letting d be NONE, because tl of a list with one element returns an empty list. isSome d will be false, which is why we will return SOME(hd dates) — the only element, which is by definition the oldest.
Assuming the function works for the case of a list of n-1 items, let's see what happens when the list has n items: We will go into the else branch and assign to d the oldest element from the tail of the list (which works, because it contains n-1 items). Now there's two possible scenarios:
a. d is older than the first element of the list. In that case, d will be returned, because both isSome d and is_older(valOf d, hd dates) will be true.
b. d is not older than the first element of the list. We will therefore return SOME(hd dates) — the first element of the list.
We have shown that it works for n elements if it works for n-1, and we have shown that it works for n=0 and n=1 (technically we could have skipped step 2). It will therefore work for a list of any size.

Get Nth combination of a set of elements with loose conditions

Given:
A list of symbols of size M
The desired size of combination L
Symbols may occur any number of times in a combination
All permutations of any combination of the symbols must be taken into the account
Example: for a list of symbols (a, b, c), and L=4, all of the combinations (a, a, a, a), (a, b, a, c), (a, c, b, b) and so on are valid. For the lack of a better term, I called this "loose combinations".
The particular ordering of the combinations is not important. Being given the combination index N, the algorithm should return a unique combination from the set of possible combinations that satisfy the conditions. My guess is that the most natural order would be if we consider the combinations as numbers of radix M and length L, so that the normal number order would apply, but that is not strictly necessary to follow.
What is the algorithm to find the Nth combination?
I'm not sure how to find the answer myself, and have been searching if there was an answer for this particular set of conditions elsewhere, but did not find it. All the questions that I find are not interested in combinations with repeating elements like (a, a, b, b) and combinations with rearranged order, like (a, a, b, c) and (a, b, c, a) or (a, c, a, b) are treated as the same combination.
As you figured out already, you are essentially interested in enumerating the numbers of length up to L in base M.
So, a solution might look like this:
Define a bijection {0, …, M-1} -> Symbols, i.e. enumerate your symbols.
For any non-negative integer N < M^L, determine its base M representation.
Easily done by repeated modulo M and rounded down division by M.
Without loss of generality, this has length M by adding leading zeroes as needed.
Use your bijection to convert this list of digits 0 to M-1 to a loose combination of symbols.
So, let's go into detail on this part:
Easily done by repeated modulo M and rounded down division by M.
Pseudocode:
int a[L];
for int i from 0 to L-1 do
a[i] = N % M; // Should go from 0 to M-1
N = N / M; // Rounded down, of course
done

The Eight-Queen Puzzle in Programming in Lua Fourth Edition

I'm currently reading Programming in Lua Fourth Edition and I'm already stuck on the first exercise of "Chapter 2. Interlude: The Eight-Queen Puzzle."
The example code is as follows:
N = 8 -- board size
-- check whether position (n, c) is free from attacks
function isplaceok (a, n ,c)
for i = 1, n - 1 do -- for each queen already placed
if (a[i] == c) or -- same column?
(a[i] - i == c - n) or -- same diagonal?
(a[i] + i == c + n) then -- same diagonal?
return false -- place can be attacked
end
end
return true -- no attacks; place is OK
end
-- print a board
function printsolution (a)
for i = 1, N do -- for each row
for j = 1, N do -- and for each column
-- write "X" or "-" plus a space
io.write(a[i] == j and "X" or "-", " ")
end
io.write("\n")
end
io.write("\n")
end
-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
if n > N then -- all queens have been placed?
printsolution(a)
else -- try to place n-th queen
for c = 1, N do
if isplaceok(a, n, c) then
a[n] = c -- place n-th queen at column 'c'
addqueen(a, n + 1)
end
end
end
end
-- run the program
addqueen({}, 1)
The code's quite commented and the book's quite explicit, but I can't answer the first question:
Exercise 2.1: Modify the eight-queen program so that it stops after
printing the first solution.
At the end of this program, a contains all possible solutions; I can't figure out if addqueen (n, c) should be modified so that a contains only one possible solution or if printsolution (a) should be modified so that it only prints the first possible solution?
Even though I'm not sure to fully understand backtracking, I tried to implement both hypotheses without success, so any help would be much appreciated.
At the end of this program, a contains all possible solutions
As far as I understand the solution, a never contains all possible solutions; it either includes one complete solution or one incomplete/incorrect one that the algorithm is working on. The algorithm is written in a way that simply enumerates possible solutions skipping those that generate conflicts as early as possible (for example, if first and second queens are on the same line, then the second queen will be moved without checking positions for other queens, as they wouldn't satisfy the solution anyway).
So, to stop after printing the first solution, you can simply add os.exit() after printsolution(a) line.
Listing 1 is an alternative to implement the requirement. The three lines, commented respectively with (1), (2), and (3), are the modifications to the original implementation in the book and as listed in the question. With these modifications, if the function returns true, a solution was found and a contains the solution.
-- Listing 1
function addqueen (a, n)
if n > N then -- all queens have been placed?
return true -- (1)
else -- try to place n-th queen
for c = 1, N do
if isplaceok(a, n, c) then
a[n] = c -- place n-th queen at column 'c'
if addqueen(a, n + 1) then return true end -- (2)
end
end
return false -- (3)
end
end
-- run the program
a = {1}
if not addqueen(a, 2) then print("failed") end
printsolution(a)
a = {1, 4}
if not addqueen(a, 3) then print("failed") end
printsolution(a)
Let me start from Exercise 2.2 in the book, which, based on my past experience to explain "backtracking" algorithms to other people, may help to better understand the original implementation and my modifications.
Exercise 2.2 requires to generate all possible permutations first. A straightforward and intuitive solution is in Listing 2, which uses nested for-loops to generate all permutations and validates them one by one in the inner most loop. Although it fulfills the requirement of Exercise 2.2, the code does look awkward. Also it is hard-coded to solve 8x8 board.
-- Listing 2
local function allsolutions (a)
-- generate all possible permutations
for c1 = 1, N do
a[1] = c1
for c2 = 1, N do
a[2] = c2
for c3 = 1, N do
a[3] = c3
for c4 = 1, N do
a[4] = c4
for c5 = 1, N do
a[5] = c5
for c6 = 1, N do
a[6] = c6
for c7 = 1, N do
a[7] = c7
for c8 = 1, N do
a[8] = c8
-- validate the permutation
local valid
for r = 2, N do -- start from 2nd row
valid = isplaceok(a, r, a[r])
if not valid then break end
end
if valid then printsolution(a) end
end
end
end
end
end
end
end
end
end
-- run the program
allsolutions({})
Listing 3 is equivalent to List 2, when N = 8. The for-loop in the else-end block does what the whole nested for-loops in Listing 2 do. Using recursive call makes the code not only compact, but also flexible, i.e., it is capable of solving NxN board and board with pre-set rows. However, recursive calls sometimes do cause confusions. Hope the code in List 2 helps.
-- Listing 3
local function addqueen (a, n)
n = n or 1
if n > N then
-- verify the permutation
local valid
for r = 2, N do -- start from 2nd row
valid = isplaceok(a, r, a[r])
if not valid then break end
end
if valid then printsolution(a) end
else
-- generate all possible permutations
for c = 1, N do
a[n] = c
addqueen(a, n + 1)
end
end
end
-- run the program
addqueen({}) -- empty board, equivalent allsolutions({})
addqueen({1}, 2) -- a queen in 1st row and 1st column
Compare the code in Listing 3 with the original implementation, the difference is that it does validation after all eight queens are placed on the board, while the original implementation validates every time when a queen is added and will not go further to next row if the newly-added queen causes conflicts. This is all what "backtracking" is about, i.e. it does "brute-force" search, it abandons the search branch once it finds a node that will not lead to a solution, and it has to reach a leaf of the search tree to determine it is a valid solution.
Back to the modifications in Listing 1.
(1) When the function hits this point, it reaches a leaf of the search tree and a valid solution is found, so let it return true representing success.
(2) This is the point to stop the function from further searching. In original implementation, the for-loop continues regardless of what happened to the recursive call. With modification (1) in place, the recursive call returns true if a solution was found, the function needs to stop and to propagate the successful signal back; otherwise, it continues the for-loop, searching for other possible solutions.
(3) This is the point the function returns after finishing the for-loop. With modification (1) and (2) in place, it means that it failed to find a solution when the function hits this point, so let it explicitly return false representing failure.

Prolog query fails

This is supposed to calculate the sum of two lists. The lists can be of different size.
sum([],[],[]).
sum(A,[],A).
sum([],B,B).
sum([A|Int1],[B|Int2],[C|Int3]) :-
(
C =:= A + B
;
((C =:= A), B = [])
;
((C =:= B), A = [])
),
sum(Int1,Int2,Int3).
It seems to work correctly, except when trying to find the sum of two lists. Then it gives the following error:
ERROR: =:=/2: Arguments are not sufficiently instantiated
I don't see why. There's a recursive and a basis step, what exactly is not yet instantiated and how do I fix it?
[1] While your disjunctions in the last clause are -- to some extent -- conceptually correct, Prolog considers these disjunctions in sequence. So it first considers C =:= A + B. But either A or B can be the empty list! This is what causes the error you reported, since the empty list is not allowed to occur in a numeric operation.
[2] You need to use C is A + b (assignment) i.o. C =:= A + B (numeric equivalence).
[3] If you say [A|Int1] and then A = [], then this means that [A|Int1] is not (only) a list of integers (as you claim it is) but (also) a list of lists! You probably intend to check whether the first or the second list is empty, not whether either contains the empty list.
Staying close to your original program, I would suggest to reorder and change things in the following way:
sumOf([], [], []):- !.
sumOf([], [B|Bs], [C|Cs]):- !,
C is B,
sumOf([], Bs, Cs).
sumOf([A|As], [], [C|Cs]):- !,
C is A,
sumOf(As, [], Cs).
sumOf([A|As], [B|Bs], [C|Cs]):-
C is A + B,
sumOf(As, Bs, Cs).
For example:
?- sumOf([1,2,3], [1,-90], X).
X = [2, -88, 3]
Notice my use of the cut (symbol !) in the above. This makes sure that the same answer is not given multiple times or -- more technically -- that no choicepoints are kept (and is called determinism).
You should read a tutorial or a book. Anyway, this is how you add two things to each other:
Result is A + B
This is how you could add all elements of one list:
sum([], 0). % because the sum of nothing is zero
sum([X|Xs], Sum) :-
sum(Xs, Sum0),
Sum is X + Sum0.
And this is how you could add the sums of a list of lists:
sums([], 0).
sums([L|Ls], Sums) :-
sums(Ls, Sums0),
sum(L, S),
Sums is Sums0 + S.

Resources