In F# im trying to remove an occurence in the set if a condition is met, however it's not really working they way i'd like it to.
The trick to removing elements from a set is the function Set.filter, which takes a function as an argument - filter will feed in every value of the set to your function, and add it to a new set if the function returns true. An example implementation might be:
let filter f (original : Set<'T>) =
set [ for value in original do if f value then yield value ]
which has type filter : ('T -> bool) -> Set<'T> -> Set<'T>. An example of using it would be
filter (fun x -> x % 2 = 0) (set [ 1; 2; 3; 4; 5 ])
This filters the set for even numbers, so the return value would be set [ 2; 4 ].
I'm not entirely sure what problem you're having exactly, but here is a solution to the game Mastermind using Knuth's algorithm, albeit with a random starting guess, rather than his choice of "1122".
I thought it was quite a nice exercise, though writing the checkGuess function was the hardest part of it for me!
You can run a test by opening this in F# interactive by running the function playMastermind (), which will show you its guesses.
/// The colours that pegs are allowed to be.
type Peg = Blue | Red | Green | Yellow | Purple | Brown
/// A shared instance of the System.Random () class for all the random number
/// generators.
let private rnd = new System.Random ()
/// Make a random set of four peg colours.
let randomGuess () =
let randomPeg () =
match rnd.Next(1, 6) with
| 1 -> Blue
| 2 -> Red
| 3 -> Green
| 4 -> Yellow
| 5 -> Purple
| 6 -> Brown
| _ -> failwith "Random number generation failed."
[ randomPeg (); randomPeg (); randomPeg (); randomPeg () ]
/// Iterate over the colours to make all of the possible combinations.
let allPossibles =
let colours = [ Blue; Red; Green; Yellow; Purple; Brown]
set [ for a in colours do for b in colours do for c in colours do for d in colours -> [ a; b; c; d ] ]
/// Get the number of white and black pegs when comparing solution to guess.
let checkGuess solution guess =
/// Create a map of (colour -> count).
let toMap = List.countBy id >> Map.ofList
/// Compute how many pegs' colours are shared in the guesses.
let mapIntersect map1 map2 =
let overlap peg count =
match Map.tryFind peg map2 with
| None -> 0
| Some num -> min num count
Map.fold (fun acc peg count -> acc + overlap peg count) 0 map1
/// Simply compare to see if each peg is in the correct place.
let blacks = List.map2 (fun x y -> if x = y then 1 else 0) solution guess |> List.sum
// The number of pegs of the right colour but the wrong location is the
// same as the total number of pegs of the right colour subtract the ones
// that are also in the right place.
let whites = mapIntersect (toMap solution) (toMap guess) - blacks
whites, blacks
/// Get a random element of a set.
let randomSetElement set =
let arr = Set.toArray set
arr.[rnd.Next (Array.length arr)]
let playMastermind () =
// This creates a closure so we can check our guess against the solution,
// without storing the actual value of the solution.
let checkAnswer = checkGuess (randomGuess ())
let rec loop turnCount remaining =
if Set.count remaining = 1 then
let answer = Set.maxElement remaining
printfn "The answer is %A, which I calculated in %d turns." answer (turnCount - 1)
else
let guess = randomSetElement remaining
let (whites, blacks) = checkAnswer guess
printfn "On turn %d I guessed %A, which gave %d white pins and %d black pins." turnCount guess whites blacks
/// Remove all possibilities from the solution that wouldn't give the
/// same numbers of white and black pins and continue.
loop (turnCount + 1) (Set.filter (fun possible -> (whites, blacks) = checkGuess possible guess) remaining)
// Play the game!
loop 1 allPossibles
I'd make this a comment, but it's too long, so it needs to be an answer instead, even though it's not a complete answer to your problem.
One problem with your code, as it is now, is this section:
for candidate in candidateSet do
let scString = candidate.ToString()
let mutable secretList = []
for i = 0 to 3 do
let digit = (int scString.[i])-(int '0')
secretList <- secretList # [digit]
let tempCode = List.map (fun x -> numberToCodeColorPlus (x)) secretList
//Validate works and returns a peg set (b,w)..e.g. (0,0)
let secretCodePegs = validate guess tempCode
if secretCodePegs <> guessPegs then
candidateSet <- Set.remove candidate candidateSet
F#, like Python, uses indentation to denote blocks. So that let secretCodePegs = validate guess tempCode line is outside the for loop, not inside the for loop the way you clearly intended it to be. And the if secretCodePegs <> guessPegs then line that follows it, as far as F# is concerned, is part of a new block, and not part of the for loop any longer (because the let secretCodePegs = ... line ended the for loop). All you need to do is indent the let secretCodePegs = ... line by one level, and your code will work. In other words, that section should have looked like this:
for candidate in candidateSet do
let scString = candidate.ToString()
let mutable secretList = []
for i = 0 to 3 do
let digit = (int scString.[i])-(int '0')
secretList <- secretList # [digit]
let tempCode = List.map (fun x -> numberToCodeColorPlus (x)) secretList
//Validate works and returns a peg set (b,w)..e.g. (0,0)
let secretCodePegs = validate guess tempCode
if secretCodePegs <> guessPegs then
candidateSet <- Set.remove candidate candidateSet
Related
I would like to be able to generate random numbers that all meet a given predicate, for example only generate random numbers that are even or prime. Is there an algorithm to do this in a relatively efficient way? The way I have found to do this is to go brute-force:
let randIntSatisfy (randGenerator: System.Random) (satisfy: int -> bool) =
// The maximum number of tries before returning `None`
let maxTry = 100
let rec inner i =
function
| num when satisfy num -> Some num
| num when not (satisfy num) && (i < maxTry) -> inner (i + 1) (randGenerator.Next())
| _ -> None
inner 0 (randGenerator.Next())
let example =
let randGen = new System.Random()
seq { for _ = 0 to 10 do
yield randIntSatisfy randGen (fun x -> x % 2 = 0) }
This code will not loop forever but will not guarantee to find a number that satisfies the given predicate (assuming such a number exists of course, if I ask for a negative number, then the function will return None all the time for example). Is there a way to do a little better than that?
PS: I've used F# here, but I'm not specifically asking for a language-specific answer.
Background
I am trying to model a system that can change its configurations each time step. The variety of configurations is known in advance and does not depend on the time step. Transitions are allowed between certain configurations and forbidden between others. The objective is to build an adjacency connectivity matrix of allowed transitions, which spans multiple time steps.
Setting
Let A be an s*s*k logical matrix representing allowed transitions, and A1...Ak represent the pages/slices of A:
A1 = A(:,:,1); A2 = A(:,:,2); ... Ak = A(:,:,k);
The meaning of the 3rd dimension is how many time steps are required for a transition, for example: if A(1,3,2) is nonzero, it means that state #1 can transition to state #3 and this will take 2 time steps.
Let B be the adjacency matrix that we want to build, which represents nt time steps. The shape of B should be schematically (in block matrix notation):
_ _
| [0] [A1] [A2] ... [Ak] [0] ... [0] |
B = | [0] [0] [A1] [A2] ... [Ak] ... [0] |
| ⋮ ⋮ ⋱ ⋱ ⋱ ⋮ |
|_[0] [0] … … … … … … … … [0]_| "[A1] [A2] ... [Ak]"
where the main block diagonal consists of nt 0-blocks, and the slices of A get gradually "pushed" to the right until "time runs out", the slices of A end up "outside" of B ⇒ indicating no more transitions are possible. Since B consists of nt*nt s*s blocks, its size is (nt*s)×(nt*s).
Question: Given A and nt, how can we construct B in the most CPU- and memory-efficient way?
Notes
Since B is mostly filled with zeros, it probably makes sense for it to be sparse.
CPU efficiency (runtime) is more important in my application than memory efficiency.
In the real problem, s=250 and nt=6000.
External scripts/classes/tools are welcome.
An idea I had was not constructing the matrix staggered initially, but instead having a main diagonal of [A1] blocks and circshift-ing and masking when everything else is done.
Demonstration + Naïve implementation
s = 3; k = 4; nt = 8;
A = logical(cat(3, triu(ones(s)), eye(s), zeros(s), [0 0 0; 0 0 0; 0 1 0]));
% Unwrap A (reshape into 2D):
Auw = reshape(A, s, []);
% Preallocate a somewhat larger B:
B = false(nt*s, (nt+k)*s);
% Assign Auw into B in a staggered fashion:
for it = 1:nt
B( (it-1)*s+1:it*s, it*s+1:(it+k)*s ) = Auw;
end
% Truncate the extra elements of B (from the right)
B = B(1:nt*s, 1:nt*s);
spy(B);
Resulting in:
One solution could be to calculate all the indices using implicit expansion:
% Dev-iL minimal example
s = 3; k = 4; nt = 8;
A = logical(cat(3, triu(ones(s)), eye(s), zeros(s), [0 0 0; 0 0 0; 0 1 0]));
Auw = reshape(A, s, []);
% Compute the indice:
[x,y] = find(Auw);
x = reshape(x+[0:s:s*(nt-1)],[],1);
y = reshape(y+[s:s:s*nt],[],1);
% Detection of the unneeded non zero elements:
ind = x<=s*nt & y<=s*nt;
% Sparse matrix creation:
S = sparse(x(ind),y(ind),1,s*nt,s*nt);
% Plot the results:
spy(S)
Here we only compute the position of non zero values. We avoid to preallocate a big matrix that will slow down the computation.
Benchmark:
I have used matlab online to run the benchmark, the available memory is limited. If someone would run the benchmark on his local computer with bigger value, feel free to do so.
With those configurations, it seems that using implicit expansion is indeed faster.
Benchmark code:
for ii = 1:100
s = ii; k = 4; nt = ii;
Auw = rand(s,s*k)>0.75;
f_expa = #() func_expansion(s,nt,Auw);
f_loop = #() func_loop(s,k,nt,Auw);
t_expa(ii) = timeit(f_expa);
t_loop(ii) = timeit(f_loop);
end
plot(1:100,t_expa,1:100,t_loop)
legend('Implicit expansion','For loop')
ylabel('Runtime (s)')
xlabel('x and nt value')
% obchardon suggestion
function S = func_expansion(s,nt,Auw)
[x,y] = find(Auw);
x = reshape(x+[0:s:s*(nt-1)],[],1);
y = reshape(y+[s:s:s*nt],[],1);
ind = x<=s*nt & y<=s*nt;
S = sparse(x(ind),y(ind),1,s*nt,s*nt);
end
% Dev-il suggestion
function B = func_loop(s,k,nt,Auw)
B = false(nt*s, (nt+k)*s);
for it = 1:nt
B( (it-1)*s+1:it*s, it*s+1:(it+k)*s ) = Auw;
end
B = B(1:nt*s, 1:nt*s);
end
I have a large relation in which each tuple has an integer value corresponding to each column. Now I need to display these tuples in an order according the user specified priorities of each column(which obviously change according to the user). Miniature example:
Consider this relation:
A user enters priorities as 8,9,5 and 4 for A,B,C and D respectively, I need to determine the order of the tuples matching best to user priorities.
What I have thought of till now is applying filters in the sorted order of the provided user priorities and then displaying the results. I need help for a more accurate algorithm.
Might the answer be as simple as...?
Obviously, this is not the answer, yet I am still in the dark, what the correct result might be...
Basically the question comes down to "Which metric is to the best taste of the user?".
While offering 2 metrics myself, anyone who has ideas can shorten their answers by giving a metric function. You can experiment with the code below for example at http://www.tryfsharp.org/Create
The first (metric1 uses the scalar product).
While the second value is small, the first value with nearly as high a priority gets (6,2,3,8) up in the rankings.
The second (metric2) attempts to be value agnostic, using some ranking method (ranking as in robust estimators, baysean, ...) where a match in the position of the sorted tuple values relative to the positions in the sorted priority tuple is rewarded with a number which is 2^(priority position). This means, that a match in the rank for the highest priority can never be beaten by a lower priority position match. You still follow, right? :)
To clarify metric2 a bit more (and I am sure it can be improved - where are those google guys when you need them?!):
[3; 2; 4; 1] [2; 1; 3; 4] ([1; 5; 9; 2] [8; 9; 5; 4])
0
[4; 1; 3; 2] [2; 1; 3; 4] ([6; 2; 3; 8] [8; 9; 5; 4])
12
[4; 3; 2; 1] [2; 1; 3; 4] ([4; 4; 4; 4] [8; 9; 5; 4])
0
Here you see intermediate values for metric2 for all 3 4-tuples in the table.
Rightmost you see the priority value tuple. Second from right, the input value tuple. The first two lists show the sorting indices (in descending order) for both the table tuple and the priority tuple.
Now... a good match would have the same sorting order as the priority tuple. (This metrics theory). So if the biggest value in the table tuple would be located where the highest priority in the priority tuple is located, this would be good. And for high priority positions in the priority tuple this is even better. If the second highest value in the table tuple is at the position of the second highest priority value in the priority tuple, this is also nice - but not as important as the first value on the highest priority...
To avoid that the ordering of the least "significant" values in the tuple according to the priority tuple win over the more "significant" ones, I added a priority specific value to the metrics.
If the first priority is matched, it gets the metric value 2^4 = 16. If the second matches it is 8, then 4,2,1. So even if the first match failed and all the others are matched, a tuple cannot beat a tuple where the first one is in the right spot.
For the researchers convenience, I added an empty metric3 which can be used for finding better alternatives.
let ua,ub,uc,ud = (8,9,5,4)
let table = [ 1,5,9,2; 6,2,3,8; 4,4,4,4 ]
let metric1 (a,b,c,d) = a*ua + b * ub + c * uc + d * ud
let metric2 (a,b,c,d) =
let indices = [1;2;3;4]
let values = [a;b;c;d]
let indByValue =
List.zip indices values
|> List.sortBy (fun (i,v) -> v)
|> List.map (fun (i,v) -> i)
|> List.rev
let prioIndByValue =
List.zip indices [ua;ub;uc;ud]
|> List.sortBy (fun (i,p) -> p)
|> List.map (fun (i,p) -> i)
|> List.rev
//printfn "%A %A (%A %A)" indByValue prioIndByValue values [ua;ub;uc;ud]
let r,_ =
List.zip indByValue prioIndByValue
|> List.fold (fun (cnt,w) (x,y)-> if x = y then (cnt + (1 <<< w),w-1) else (cnt,w-1) ) (0,4)
r
let metric3 (a,b,c,d) =
// TODO: Write your favourite metric here ;)
0
let best1 = List.maxBy metric1 table
let sorted1 = List.sortBy metric1 table
let best2 = List.maxBy metric2 table
let sorted2 = List.sortBy metric2 table
let best3 = List.maxBy metric3 table
let sorted3 = List.sortBy metric3 table
//table |> List.iter (fun r -> printfn "%A" (metric2 r))
Last Friday, in a French programming contest, we were given a paper folding problem which was as follows:
Given a square sheet of paper and a folding pattern, write a function "fold(pattern)" that will give the order of the layers that will result from the cumulative folding (in half) of the sheet in respect of the pattern."
That may not be very clear, so let me explain a bit (having a square sheet of paper handy might help to understand, if you're willing to go that far to help me out).
Suppose that we have a square sheet of paper which we draw a N*N grid on and then number all its inner squares. Given a pattern "LTRB", we would fold this paper vertically in half and put the resulting left part on to the right part. Then, we would fold it horizontally and put the top part onto the bottom part. Then, we would fold it vertically again and put the right part onto the left part. Finally, we would fold it horizontally and put the bottom part on the top part. This leaves us with a sheet of paper that is the size of one square and N^2 layers. The expected answer is the resulting order of each original square.
For example, if we have a draw a 2*2 grid on a square sheet of paper and then number each inner square from 1 to 4 (top left to bottom right, horizontally), and given the pattern "LT", we would have this happening:
fold("LT"):
1 | 2 L 1,2 T
---|--- ==> --- ==> 2,1,3,4
3 | 4 3,4
and with a "RB" pattern, for example:
fold("RB"):
1 | 2 R 2,1 B
---|--- ==> --- ==> 3,4,2,1
3 | 4 4,3
As you would have probably guessed, it basically boils down to a recursive transformation of an N*N matrix. This was the easy part, and here is my solution:
http://ideone.com/QaXGq
Now comes the interesting part.
Write a function unfold(order) that will, for a given resulting layer
ordering, give the pattern that produced this ordering. Note that
unfold(fold("LRTB")) => "LRTB"
And then my brain stopped working for a while and I didn't have the time (2 hours left from 4 hours total) to come up with a fast enough solution.
My initial ideas were:
Try to brute force it. Because we know the length of the input is N^2, we can create an initial matrix and try all possible folding until we reach the same order as the input. O(4^N) complexity, not viable.
Brute force reverse. Start from the input, and try all unfolding possibilities until we reach a correct initial state. A little bit better, but still too slow.
???
Anyone has an idea?
At each step you only need to know the first element and the last element of your list. If the first element should be on the left of the last one, then the folding direction was left (idem with right, top and bottom).
Here's my attempt. It sounds pretty easy but as usual the devil is in the detail.
First, fold:
type Matrix = IndexedSeq[IndexedSeq[IndexedSeq[Int]]]
def initial(folds: Int): Matrix = {
val sideLen = math.pow(2, folds / 2).toInt
(1 to sideLen * sideLen) map (Vector(_)) grouped sideLen toIndexedSeq
}
def leftFold (m: Matrix): Matrix = m map { r =>
val (a, b) = r splitAt (r.size / 2)
(a.reverse, b).zipped map (_.reverse ++ _)
}
def rightFold(m: Matrix): Matrix = m map { r =>
val (a, b) = r splitAt (r.size / 2)
(b.reverse, a).zipped map (_.reverse ++ _)
}
def topFold (m: Matrix): Matrix = leftFold(m.transpose).transpose
def bottomFold(m: Matrix): Matrix = rightFold(m.transpose).transpose
def fold(input: String): Seq[Int] = {
def go(in: String, m: Matrix): Seq[Int] = in match {
case "" => m(0)(0)
case s => go(s.tail, s.head match {
case 'L' => leftFold(m)
case 'R' => rightFold(m)
case 'T' => topFold(m)
case 'B' => bottomFold(m)
})
}
go(input, initial(input.length))
}
Second, unfold:
def unfold(input: Seq[Int]): String = {
val m0: Matrix = Vector(Vector(Vector(input: _*)))
val sideLen = math.sqrt(input.length).toInt
def go(m: Matrix, out: String): String = {
val tl = m.head.head
val bl = m.last.head
val tr = m.head.last
if (m.length == sideLen && m.head.length == sideLen) out.reverse
else if (tl.head == tl.last - 1) go(leftUnfold(m), out + 'L')
else if (tr.head == tr.last + 1) go(rightUnfold(m), out + 'R')
else if (tl.head == tl.last - sideLen) go(topUnfold(m), out + 'T')
else if (bl.head == bl.last + sideLen) go(bottomUnfold(m), out + 'B')
else sys.error("no fold found " + m)
}
go(m0, "")
}
def leftUnfold (m: Matrix): Matrix = m map { r =>
val (a, b) = r.map(e => e.splitAt(e.size / 2)).unzip
a.map(_.reverse).reverse ++ b
}
def rightUnfold(m: Matrix): Matrix = m map { r =>
val (a, b) = r.map(e => e.splitAt(e.size / 2)).unzip
b ++ a.map(_.reverse).reverse
}
def topUnfold (m: Matrix): Matrix = leftUnfold (m.transpose).transpose
def bottomUnfold(m: Matrix): Matrix = rightUnfold(m.transpose).transpose
I ran a few tests and it passed...
I have the following list:
["A";"AA";"ABC";"BCD";"B";"C"]
I am randomly extracting an element from the list. But the element I extract should be of size 3 only not lesser than 3.
I am trying to do this as follows:
let randomnum = (Random.int(List.length (list)));;
let rec code c =
if (String.length c) = 3 then c
else (code ((List.nth (list) (randomnum)))) ;;
print_string (code ( (List.nth (list) (randomnum)))) ;;
This works fine if randomly a string of length 3 is picked out from the list.
But the program does not terminate if a string of length < 3 is picked up.
I am trying to do a recursive call so that new code keeps getting picked up till we get one of length = 3.
I am unable to figure out why this is does not terminate. Nothing gets output by the print statement.
What you probably want to write is
let rec code list =
let n = Random.int (List.length list) in
let s = List.nth list in
if String.length s < 3 then code list else s
Note that, depending on the size of the list and the number of strings of size greater than 3, you might want to work directly on a list with only strings greater than 3:
let code list =
let list = List.filter (fun s -> String.length s >= 3) list in
match list with
| [] -> raise Not_found
| _ -> List.nth list (Random.int (List.length list))
This second function is better, as it always terminate, especially when there are no strings greater than 3.
You only pick a random number once. Say you pick 5. You just keep recursing with 5 over and over and over. You need to get a new random number.
For your code to terminate, it would be better to first filter the list for suitable elements, then take your random number:
let code list =
let suitables = List.filter (fun x -> String.length x = 3) list in
match List.length suitables with
| 0 -> raise Not_found (* no suitable elements at all! *)
| len -> List.nth suitables (Random.int len)
Otherwise your code would take very long to terminate on a large list of elements with size <> 3; or worse on a list with no element of size 3, it would not terminate at all!