The function takes 2 arguments: array: int[], cap: int
Members would be ranged from 0 to cap.
e.g.
array = [0,0,0,2,6,3,0,4,2,4,0]
cap = 6
The return value is a new array of same length based on these rules:
The function can only change values of consecutive elements which are > 0. i.e. any where the original array has 0, the new array has 0 as well.
In a consecutive series of elements which are > 0, if the maximum of it equals cap, then in the new array they are changed to 1,1,...,1,cap of the same length. e.g. 0,2,6,4,0 -> 0,1,1,6,0
In a consecutive series of elements which are > 0, if the maximum of it is smaller than cap, then the elements in the new array are mapped to either 1 or maximum (if the element value < maximum then 1, otherwise maximum ) . e.g. 0,2,5,5,0 -> 0,1,5,5,0
So the sample array would map to [0,0,0,1,1,6,0,4,1,4,0]
The following are my code which are implemented in both languages, it surprises me that F# takes same lines as C#.
I would like to suggestions to improve either language.
F#
open System
let private reorder cap (array: int[]) =
if Array.isEmpty array then
array
else
let max = array |> Array.max
if max = cap then
let newArray = Array.create array.Length 1
newArray.[array.Length-1] <- cap
newArray
else
array |> Array.map (fun elem -> if elem = max then max else 1)
let private getZeroes todo =
todo |> Seq.takeWhile (fun elem -> elem = 0)
|> Seq.toArray
let private getNumbers todo cap =
todo |> Seq.takeWhile (fun elem -> elem <> 0)
|> Seq.toArray
|> reorder cap
let GetEquivalentPermutation (array: int[], cap) =
let rec joinParts finished todo =
if Seq.isEmpty todo then finished |> Seq.toArray
else
let zeroes = getZeroes todo
let nextTodo = todo |> Seq.skip zeroes.Length
let numbers = getNumbers nextTodo cap
let finalTodo = nextTodo |> Seq.skip numbers.Length
let newFinished = Seq.append (Seq.append finished zeroes) numbers
joinParts newFinished finalTodo
joinParts [] array
C#
static int[] EquivalentOutput(int cap, int[] permutation)
{
IEnumerable<int> right = permutation;
List<int> equivalentLine = new List<int>();
while (right.Any())
{
var leftArray = right.TakeWhile(x => x != 0).ToArray();
List<int> leftEquivalent;
if (leftArray.Length == 0)
{
leftEquivalent = new List<int>();
}
else if (leftArray.Length != 1)
{
int max = leftArray.Max();
if (max == cap)
{
leftEquivalent = leftArray.Take(leftArray.Length - 1).Select(x => 1).ToList();
leftEquivalent.Add(cap);
}
else
{
leftEquivalent = leftArray.Select(x => x < max ? 1 : max).ToList();
}
}
else
{
leftEquivalent = leftArray.ToList();
}
equivalentLine.AddRange(leftEquivalent);
equivalentLine.AddRange(right.SkipWhile(x => x != 0).TakeWhile(x => x == 0));
right = right.SkipWhile(x => x != 0).SkipWhile(x => x == 0);
}
return equivalentLine.ToArray();
}