View Problem
Subdivide A Problem To A Pool Of Workers (No Shared Data)
Take a hard to compute problem and split it up between multiple worker threads. In your solution, try to fully utilize available cores or processors. (I'm looking at you, Python!)
Note: In this question, there should be no need for shared state between worker threads while the problem is being solved. Only after every thread completes computation are the answers recombined into a single output.
Example:
-Input-
(In python syntax)
In other words, a list of random strings.
-Output-
(In python syntax)
In other words, all possible permutations of each input string are computed.
Submit a new solution for ruby, cpp, fsharp, or clojure
There are 8 other solutions in additional languages (fantom, groovy, haskell, java ...)
Note: In this question, there should be no need for shared state between worker threads while the problem is being solved. Only after every thread completes computation are the answers recombined into a single output.
Example:
-Input-
(In python syntax)
["ab", "we", "tfe", "aoj"]
In other words, a list of random strings.
-Output-
(In python syntax)
[ ["ab", "ba", "aa", "bb", "a", "b"], ["we", "ew", "ww", "ee", "w", "e"], ...
In other words, all possible permutations of each input string are computed.
cpp OpenMP
vector<string> input;
input.push_back("ab");
input.push_back("we");
input.push_back("tfe");
input.push_back("aoj");
// Make the capacity for 'output' the same as 'input'
vector<set<string> > output(input.size());
#pragma omp parallel for
for (int i = 0; i < input.size(); ++i) {
set<string> perms;
generate_perms(input[i], perms);
#pragma omp critical
// Must use operator[]() and not push_back() since this line
// might be called in any order with respect to 'i'
output[i] = perms;
}
cout << output << endl;
input.push_back("ab");
input.push_back("we");
input.push_back("tfe");
input.push_back("aoj");
// Make the capacity for 'output' the same as 'input'
vector<set<string> > output(input.size());
#pragma omp parallel for
for (int i = 0; i < input.size(); ++i) {
set<string> perms;
generate_perms(input[i], perms);
#pragma omp critical
// Must use operator[]() and not push_back() since this line
// might be called in any order with respect to 'i'
output[i] = perms;
}
cout << output << endl;
fsharp
open System
let input = [| "ab"; "we"; "tfe"; "aoj" |]
/// Computes all permutations of an array
let rec permute = function
| [| |] -> [| [| |] |]
| a ->
a
|> Array.mapi (fun i ai ->
// Take all elements in the array apart from the i.th, compute
// their permutations, then attach element i at the front of each perm
Array.sub a 0 i
|> Array.append (Array.sub a (i + 1) (a.Length - i - 1))
|> permute
|> Array.map (fun perm -> Array.append [| ai |] perm)
)
|> Array.concat
/// Computes all permutations of a string
let permuteString (s: string) =
s.ToCharArray()
|> permute
|> Array.map (fun p -> new String(p))
let output =
input
|> Array.map (fun word -> async { return (permuteString word) })
|> Async.Parallel
|> Async.RunSynchronously
let input = [| "ab"; "we"; "tfe"; "aoj" |]
/// Computes all permutations of an array
let rec permute = function
| [| |] -> [| [| |] |]
| a ->
a
|> Array.mapi (fun i ai ->
// Take all elements in the array apart from the i.th, compute
// their permutations, then attach element i at the front of each perm
Array.sub a 0 i
|> Array.append (Array.sub a (i + 1) (a.Length - i - 1))
|> permute
|> Array.map (fun perm -> Array.append [| ai |] perm)
)
|> Array.concat
/// Computes all permutations of a string
let permuteString (s: string) =
s.ToCharArray()
|> permute
|> Array.map (fun p -> new String(p))
let output =
input
|> Array.map (fun word -> async { return (permuteString word) })
|> Async.Parallel
|> Async.RunSynchronously
fsharp .NET 4
// like the Java and Groovy solutions, does not duplicate letters
open System
open System.Threading.Tasks
let input = [| "ab"; "we"; "tfe"; "aoj" |]
let factorial n =
seq { 1 .. n } |> Seq.reduce (*)
let swap (arr:'a[]) i j =
[| for k = 0 to arr.Length - 1 do
yield if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]
let rec permutation (k:int,j:int) (r:'a[]) =
if j = (r.Length + 1) then r
else permutation (k/j+1, j+1) (swap r (j-1) (k%j))
let permutations (source:'a[]) = seq {
for k = 0 to (factorial source.Length) - 1 do
yield permutation (k,2) source
}
let permute (word:string) =
let letters = word.ToCharArray()
permutations letters
|> Seq.map (fun chars -> String(chars))
|> Array.ofSeq
let tasks =
input |> Array.map (fun word -> Task.Factory.StartNew(fun () -> permute word))
let taskResult (t:Task<_>) =
t.Result
let output = Task.Factory.ContinueWhenAll(tasks, fun ts -> Array.map taskResult ts).Result
open System
open System.Threading.Tasks
let input = [| "ab"; "we"; "tfe"; "aoj" |]
let factorial n =
seq { 1 .. n } |> Seq.reduce (*)
let swap (arr:'a[]) i j =
[| for k = 0 to arr.Length - 1 do
yield if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]
let rec permutation (k:int,j:int) (r:'a[]) =
if j = (r.Length + 1) then r
else permutation (k/j+1, j+1) (swap r (j-1) (k%j))
let permutations (source:'a[]) = seq {
for k = 0 to (factorial source.Length) - 1 do
yield permutation (k,2) source
}
let permute (word:string) =
let letters = word.ToCharArray()
permutations letters
|> Seq.map (fun chars -> String(chars))
|> Array.ofSeq
let tasks =
input |> Array.map (fun word -> Task.Factory.StartNew(fun () -> permute word))
let taskResult (t:Task<_>) =
t.Result
let output = Task.Factory.ContinueWhenAll(tasks, fun ts -> Array.map taskResult ts).Result
clojure
(defn perm-chars [l]
"Returns a list of all possible permutations of strings with the
same size as the input string. This function will return duplicates
if the same character occurs multiple time in the string.
Ex: ab -> (aa ab ba ab)"
(if (string? l)
(recur (repeat (count l) l))
(let [s (first l)
r (rest l)]
(if (empty? r)
(map identity s)
(->> s
(map (fn [c] (map #(str c %) (perm-chars r))))
(flatten))))))
(defn perm-sz [s]
"Returns a list of all possible permutations of the input
string. May return duplicats.
Ex: ab -> (aa ab ba bb a b a b)"
(if-not (empty? s)
(let [r (perm-chars s)]
(if (= (count s) 1)
r
(->> r
(map #(perm-sz (apply str (rest %))))
(flatten)
(lazy-cat r))))))
(defn perm [s]
"Returns a list of all possible permutations of the input
string. The list of string is sorted and does not contain
duplicates.
Ex: ab -> (a aa ab b ba bb)"
(->> (reduce (fn [s e] (conj s e)) #{} (perm-sz s))
(map str)
(sort)))
(println (pmap perm ["ab" "we" "tfe" "aoj"]))
"Returns a list of all possible permutations of strings with the
same size as the input string. This function will return duplicates
if the same character occurs multiple time in the string.
Ex: ab -> (aa ab ba ab)"
(if (string? l)
(recur (repeat (count l) l))
(let [s (first l)
r (rest l)]
(if (empty? r)
(map identity s)
(->> s
(map (fn [c] (map #(str c %) (perm-chars r))))
(flatten))))))
(defn perm-sz [s]
"Returns a list of all possible permutations of the input
string. May return duplicats.
Ex: ab -> (aa ab ba bb a b a b)"
(if-not (empty? s)
(let [r (perm-chars s)]
(if (= (count s) 1)
r
(->> r
(map #(perm-sz (apply str (rest %))))
(flatten)
(lazy-cat r))))))
(defn perm [s]
"Returns a list of all possible permutations of the input
string. The list of string is sorted and does not contain
duplicates.
Ex: ab -> (a aa ab b ba bb)"
(->> (reduce (fn [s e] (conj s e)) #{} (perm-sz s))
(map str)
(sort)))
(println (pmap perm ["ab" "we" "tfe" "aoj"]))
Submit a new solution for ruby, cpp, fsharp, or clojure
There are 8 other solutions in additional languages (fantom, groovy, haskell, java ...)




