let getValue number divisor =
let firstNumber = int (System.Math.Floor((float) number / (float) divisor))
let rest = number % divisor
firstNumber, rest
let getNumeral value =
match value with
| (1, 1) -> "I"
| (5, 1) -> "V"
| (1, 2) -> "X"
| (5, 2) -> "L"
| (1, 3) -> "C"
| (5, 3) -> "D"
| (1, 4) -> "M"
| (_,_) -> ""
let getStringRepresentation value =
match value with
| (1 , order) ->
getNumeral (1, order)
| (2, order) ->
getNumeral (1, order) + getNumeral (1, order)
| (3, order) ->
getNumeral (1, order) + getNumeral (1, order) + getNumeral (1, order)
| (4, order) ->
getNumeral (1, order) + getNumeral (5, order)
| (5, order) ->
getNumeral (5, order)
| (6, order) ->
getNumeral (5, order) + getNumeral (1, order)
| (7, order) ->
getNumeral (5, order) + getNumeral (1, order) + getNumeral (1, order)
| (8, order) ->
getNumeral (5, order) + getNumeral (1, order) + getNumeral (1, order) + getNumeral (1, order)
| (9, order) ->
getNumeral (1, order) + getNumeral (1, order + 1)
| (_, _) -> ""
let rec convertToRoman number =
match number with
| number when number >= 1000 && number < 4000 ->
let value = getValue number 1000
let rest = convertToRoman (snd value)
let current = getStringRepresentation ((fst value), 4)
current + rest
| number when number >= 100 && number < 1000 ->
let value = getValue number 100
let rest = convertToRoman (snd value)
let current = getStringRepresentation ((fst value), 3)
current + rest
| number when number >= 10 && number < 100 ->
let value = getValue number 10
let rest = convertToRoman (snd value)
let current = getStringRepresentation ((fst value), 2)
current + rest
| number when number >= 1 && number < 10 ->
let value = getValue number 1
let rest = convertToRoman (snd value)
let current = getStringRepresentation ((fst value), 1)
current + rest
| _ -> ""
printfn "%A" (convertToRoman 49)
I'm new to F# and the whole functional programming. Coming from C# I've decided to start with something easy. I'm trying to keep things simple for this time being. However, I have some trouble with calling some methods multiple times (getStringRepresentation) and I also think that the recursion could use some clean up, but I don't know how.
Any ideas how to call the function twice?
As far as I can understand from the comments, what you really don't like is something like this:
getNumeral (1, order) + getNumeral (1, order) + getNumeral (1, order)
What you can do is to define another function which will let you repeat those calls:
let repeatOnes count order =
let one _ = getNumeral (1, order)
Seq.init count one |> Seq.reduce (+)
It uses Seq.init to initialize a sequence of function calls repeated count times. It then uses Seq.reduce to concatenate each of the resulting strings using the + operator. This enables you to write the above expression like this:
repeatOnes 3 order
As a first refactoring, then, you can replace all the occurances of getNumeral (1, order) like this:
let getStringRepresentation value =
match value with
| (1 , order) ->
repeatOnes 1 order
| (2, order) ->
repeatOnes 2 order
| (3, order) ->
repeatOnes 3 order
| (4, order) ->
repeatOnes 1 order + getNumeral (5, order)
| (5, order) ->
getNumeral (5, order)
| (6, order) ->
getNumeral (5, order) + repeatOnes 1 order
| (7, order) ->
getNumeral (5, order) + repeatOnes 2 order
| (8, order) ->
getNumeral (5, order) + repeatOnes 3 order
| (9, order) ->
repeatOnes 1 order + getNumeral (1, order + 1)
| (_, _) -> ""
However, you can now compact the patterns a bit:
let getStringRepresentation value =
match value with
| (count , order) when 1 <= count && count <= 3 ->
repeatOnes count order
| (4, order) ->
repeatOnes 1 order + getNumeral (5, order)
| (5, order) ->
getNumeral (5, order)
| (count, order) when 6 <= count && count <= 8 ->
getNumeral (5, order) + repeatOnes (count - 5) order
| (9, order) ->
repeatOnes 1 order + getNumeral (1, order + 1)
| (_, _) -> ""
Doing this in FSI:
> [1..50] |> List.map convertToRoman
produces this:
val it : string list =
["I"; "II"; "III"; "IV"; "V"; "VI"; "VII"; "VIII"; "IX"; "X"; "XI"; "XII";
"XIII"; "XIV"; "XV"; "XVI"; "XVII"; "XVIII"; "XIX"; "XX"; "XXI"; "XXII";
"XXIII"; "XXIV"; "XXV"; "XXVI"; "XXVII"; "XXVIII"; "XXIX"; "XXX"; "XXXI";
"XXXII"; "XXXIII"; "XXXIV"; "XXXV"; "XXXVI"; "XXXVII"; "XXXVIII"; "XXXIX";
"XL"; "XLI"; "XLII"; "XLIII"; "XLIV"; "XLV"; "XLVI"; "XLVII"; "XLVIII";
"XLIX"; "L"]
so it seems to be still working.
Related
Let's say I have this array:
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
where the first int in a tuple reports to the second int.
I can map that really easily with
let orgMap = Map.ofArray reporting
From there, I could easily get a list of all the ints that report to 2 with
orgMap
|> Map.filter (fun _ key -> key = 2)
which returns
map [(3, 2); (4, 2)]
What I'd really like to see, however, is the entire structure, from 2 all the way down. For example, I'd like to find a way that could give me the sample output
map [(3, 2); (4, 2); (5, 3); (6, 4); (7, 3)]
if I'm looking for person 2 or
map [(5, 3); (7, 3)]
if I'm interested in person 3.
Can I do this? If so, how? Is there another structure other than a map that would be a better way to make this happen?
Thanks in advance for your help.
Since OCaml is close to F# and trying to find Topological sort in F# was not turning up anything useful I looked for OCaml code.
I found An Introduction to Objective Caml which had a solution to your problem using Depth First Search and used it as the basis for this answer. Also because you are new to F# you can review the document and see how the code is derived. Oddly I took a look at the remainder of the document after posting this and he has a more advanced version of DFS latter in the document.
Your input is an array [| |] but your answer is a list [] so I did most of the work as list.
The answers are not in the same order as you had, but they are in the same format.
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
//
// 6 -> 4 -> 2
// 5 -> 3 -> 2 -> 1
// 7 -> 3
// val revStructure : tl:('a * 'b) list -> ('b * 'a) list
let revStructure tl = List.map (fun (a,b) -> (b,a)) tl
// val mem : item:'a -> list:'a list -> bool when 'a : equality
let mem item list = List.exists (fun x -> x = item) list
// val successors : n:'a -> edges:('a * 'b) list -> 'b list when 'a : equality
let successors n edges =
let matching (s,_) = s = n
List.map snd (List.filter matching edges)
// val dist : pred:'a -> succs:'b list -> ('a * 'b) list
let dist pred succs = List.map (fun y -> (pred,y)) succs
// val dfsPairs : edges:('a * 'a) list -> start:'a -> ('a * 'a) list when 'a : equality
let dfsPairs edges start =
let rec dfsPairsInner edges visited start result =
match start with
| [] -> List.rev (revStructure result)
| n::nodes ->
if mem n visited then
dfsPairsInner edges visited nodes result
else
let predecessors = dist n (successors n edges)
let result =
match predecessors with
| [] -> result
| _ -> predecessors # result
dfsPairsInner edges (n::visited) ((successors n edges) # nodes) result
dfsPairsInner edges [] [start] []
let revEdges = revStructure (List.ofArray reportStructure)
let result = dfsPairs revEdges 2
// val result : (int * int) list = [(4, 2); (3, 2); (7, 3); (5, 3); (6, 4)]
let result = dfsPairs revEdges 3
// val result : (int * int) list = [(7, 3); (5, 3)]
I assume that you want to get a list of pair of ints with "numbers" that directly or indirectly report to some "root".
Here is an easy but inefficient solution:
let reportStructure = [|(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)|]
let reportStructureSet =
reportStructure |> Set.ofArray
let reportingDirectlyTo root raportsToSet =
raportsToSet
|> Set.filter(fun (_, key) -> key = root)
let addNextGeneration previousIteration raportsToSet =
let numbersLowerInHierarchy = previousIteration |> Set.map fst
raportsToSet |> Set.filter(
// select only those elements from raportsToSet...
fun (num, supervisor) ->
// ...which either are already in previousIteration
(Set.contains (num, supervisor) previousIteration) ||
// ...or are "below" someone from previousIteration
(Set.contains supervisor numbersLowerInHierarchy))
let reportingDirectlyOrIndirectlyTo root raportsToSet =
// applies addNextGeneration until is "stabilizes" on some value
let rec fixPointHelper previousIteration =
let nextIteration = addNextGeneration previousIteration raportsToSet
if nextIteration = previousIteration
then nextIteration
else fixPointHelper nextIteration
// set of numbers directly reporting to root
let reportsDirectly = reportingDirectlyTo root raportsToSet
// start "iteration" using numbers directly reporting to root
fixPointHelper reportsDirectly
let reportingDirectlyOrIndirectlyToList root raportsToSet =
reportingDirectlyOrIndirectlyTo root raportsToSet
|> Set.toList
If you want to implement an efficient solution, you should interpret reportStructureSet as a graph in following way:
ints are vertices
pair of ints are directed edges
Then simply check which edges are reachable from "root" using a DFS.
I like f# puzzles, so I took a stab at this one. I hope that you enjoy.
let orgList = [(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)]
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
| Some(value) ->
let map' = Map.remove key acc
Map.add(key) (item::value) map'
| None ->
Map.add(key) (item::[]) acc
) Map.empty<int, (int*int) list>
let findReports supervisor =
let rec findReports' acc collection =
match collection with
| head::tail ->
(findReports' (head::acc) tail)
# match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
| [] -> acc
findReports' [] (Map.find supervisor orgMap)
findReports 2
|> List.map fst
|> List.distinct
returns
val it : int list = [3; 4; 5; 7; 6]
findReports 2 returns
val it : (int * int) list = [(3, 2); (4, 2); (5, 3); (7, 3); (6, 4)]
I'll break it down to clarify.
let orgList = [ (1, 2); (1, 3); (1, 4); (2, 5); (3, 6); (4, 5); (5, 6); (5, 7) ]
We take your list of tuples and create a functional map of boss to ((report,boss) list). This might be known as an adjacency list, which is used for traversing graphs.
let orgMap =
orgList
|> List.fold (fun acc item ->
let key = snd item
match Map.tryFind key acc with
If there is a list of reports under a boss, add to that list.
| Some(reports) ->
let map' = Map.remove key acc
Map.add(key) (item::reports) map'
Otherwise, add to an empty list and insert into the dictionary.
| None ->
Map.add(key) (item::[]) acc
Start with an empty map as an accumulator.
) Map.empty<int, (int*int) list>
Recurse through the items to find all reports.
let findReports supervisor =
let rec findReports' acc collection =
match collection with
If there is an item, append it to the accumulator. This is BFS. If you switch the expression before and after the concatenate operator (#), it will become DFS.
| head::tail ->
(findReports' (head::acc) tail)
Concatenate the current list to the recursive list of reports to reports.
# match Map.tryFind (fst head) orgMap with
| Some(value) -> (findReports' [] value)
| None -> []
If at the end of the list, return the list.
| [] -> acc
Run the recursive function.
findReports' [] (Map.find supervisor orgMap)
Run the function.
findReports 7
Return only the reports
|> List.map fst
Don't report the report twice.
|> List.distinct
I need to pack data like this:
let data = [1; 2; 2; 3; 2; 2; 2; 4]
let packed = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
Where each item say how much times it exist before the next. However, it must work with non-adjacent duplications.
I can work this with classical imperative code, but wonder how do this functionally.
Also, Seq.countBy not work because it take in account all the values
If you already have an imperative version, you can follow a set of small steps to refector to a recursive implementation.
Recursion
While I don't know what your imperative version looks like, here's a recursive version:
let pack xs =
let rec imp acc = function
| [] -> acc
| h::t ->
match acc with
| [] -> imp [(h, 1)] t
| (i, count) :: ta ->
if h = i
then imp ((i, count + 1) :: ta) t
else imp ((h, 1) :: (i, count) :: ta) t
xs |> imp [] |> List.rev
This function has the type 'a list -> ('a * int) list when 'a : equality. It uses a private 'implementation function' called imp to do the work. This function is recursive, and threads an accumulator (called acc) throughout. This accumulator is the result list, having the type ('a * int) list.
If the accumulator list is empty, the head of the original list (h), as well as the count 1, is created as a tuple as the only element of the updated accumulator, and the imp function is recursively called with that updated accumulator.
If the accumulator already contains at least one element, the element is extracted via pattern matching, and the element in that tuple (i) is compared to h. If h = i, the accumulator is updated; otherwise, a new tuple is consed on acc. In both cases, though, imp is recursively called with the new accumulator.
You can call it with a list equivalent to your original tuple like this:
> pack [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
Fold
Once you have a recursive version, you often have the recipe for a version using a fold. In this case, since the above pack function has to reverse the accumulator in the end (using List.rev), a right fold is most appropriate. In F#, this is done with the built-in List.foldBack function:
let pack' xs =
let imp x = function
| (i, count) :: ta when i = x -> (i, count + 1) :: ta
| ta -> (x, 1) :: ta
List.foldBack imp xs []
In this case, the function passed to List.foldBack is a bit too complex to pass as an anonymous function, so I chose to define it as a private inner function. It's equivalent to the recursive imp function used by the above pack function, but you'll notive that it doesn't have to call itself recursively. Instead, it just has to return the new value for the accumulator.
The result is the same:
> pack' [1; 2; 2; 3; 2; 2; 2; 4];;
val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
My solution assumes the data collection is a list. If having it as a tuple (as per your example) was intentional then for my solution to work the tuple has to be converted to a list (an example how to do it can be found here).
let groupFunc list =
let rec groupFuncRec acc lst init count =
match lst with
| [] -> List.rev acc
| head::[] when head = init
-> groupFuncRec ((init, count)::acc) [] 0 0
| head::[] when head <> init
-> groupFuncRec ((head, 1)::acc) [] 0 0
| head::tail when head = init
-> groupFuncRec acc tail head (count+1)
| head::tail when head <> init
-> groupFuncRec ((init, count)::acc) tail head 1
let t = List.tail list
let h = List.head list
groupFuncRec [] t h 1
When I run the function on your sample data I get back the expected result:
list = [(1, 1); (2, 2); (3, 1); (4, 1)]
You can get Seq.countBy to work by including some positional information in its argument. Of course, you need then to map back to your original data.
[1; 2; 2; 3; 2; 2; 2; 4]
|> Seq.scan (fun (s, i) x ->
match s with
| Some p when p = x -> Some x, i
| _ -> Some x, i + 1 ) (None, 0)
|> Seq.countBy id
|> Seq.choose (function
| (Some t, _), n -> Some(t, n)
| _ -> None )
|> Seq.toList
// val it : (int * int) list = [(1, 1); (2, 2); (3, 1); (2, 3); (4, 1)]
I'm using a slightly modified version of the RX builder presented here:
http://mnajder.blogspot.com/2011/09/when-reactive-framework-meets-f-30.html
Rather than taking IObservable<'T> directly my computational expression has a type of:
type MyType<'a,'b> = MyType of (IObservable<'a> -> IObservable<'b>)
let extract (MyType t) = t
Combinators then take on the form:
let where (f: 'b -> bool) (m:MyType<_,'b>) = MyType(fun input -> (extract m input).Where(f))
Within the expression itself, I often need to reference back to previous values that have been fed into the stream. In order to do so, I've defined a MyType which maintains a rolling immutable list of the n most recent values.
let history n =
MyType(fun input ->
Observable.Create(fun (o:IObserver<_>) ->
let buffer = new History<_>(n)
o.OnNext(HistoryReadOnly(buffer))
input.Subscribe(buffer.Push, o.OnError, o.OnCompleted)
)
)
With this, I can now do something like:
let f = obs {
let! history = history 20
// Run some other types, and possibly do something with history
}
I am finding that I am using this history quite frequently, ideally I would want to have this embedded directly into IObservable<'a>. Obviously I can't do that. So my question is, what is a reasonable way to introduce this concept of history that I have here. Should I be extending IObservable<'T> (not sure how to do that), wrapping the IObservable<'T>?
I appreciate any suggestions.
Edit: Added full example code.
open System
open System.Collections.Generic
open System.Reactive.Subjects
open System.Reactive.Linq
// Container function
type MyType<'a,'b> = MyType of (IObservable<'a> -> IObservable<'b>)
let extract (MyType t) = t
// Mini Builder
let internal mbind (myTypeB:MyType<'a,'b>) (f:'b -> MyType<'a,'c>) =
MyType(fun input ->
let obsB = extract myTypeB input
let myTypeC= fun resB -> extract (f resB) input
obsB.SelectMany(myTypeC)
)
type MyTypeBuilder() =
member x.Bind (m,f) = mbind m f
member x.Combine (a,b) = MyType(fun input -> (extract a input).Concat(extract b input))
member x.Yield (r) = MyType(fun input -> Observable.Return(r))
member x.YieldFrom (m:MyType<_,_>) = m
member x.Zero() = MyType(fun input -> Observable.Empty())
member x.Delay(f:unit -> MyType<'a,'b>) = f()
let mtypeBuilder = new MyTypeBuilder()
// Combinators
let simplehistory =
MyType(fun input ->
Observable.Create(fun (o:IObserver<_>) ->
let buffer = new List<_>()
o.OnNext(buffer)
input.Subscribe(buffer.Add, o.OnError, o.OnCompleted)
)
)
let where (f: 'b -> bool) m = MyType(fun input -> (extract m input).Where(f))
let take (n:int) m = MyType(fun input -> (extract m input).Take(n))
let buffer m = MyType(fun input -> (extract m input).Buffer(1))
let stream = MyType(id)
// Example
let myTypeResult (t:MyType<'a,'b>) (input:'a[]) = (extract t (input.ToObservable().Publish().RefCount())).ToArray().Single()
let dat = [|1 .. 20|]
let example = mtypeBuilder {
let! history = simplehistory
let! someEven = stream |> where(fun v -> v % 2 = 0) // Foreach Even
let! firstValAfterPrevMatch = stream |> take 1 // Potentially where a buffer operation would run, all values here are after i.e. we cant get values before last match
let! odd = stream |> where(fun v -> v % 2 = 1) |> take 2 // Take 2 odds that follow it
yield (history.[history.Count - 1], history.[0], someEven,firstValAfterPrevMatch, odd) // Return the last visited item in our stream, the very first item, an even, the first value after the even and an odd
}
let result = myTypeResult example dat
val result : (int * int * int * int * int) [] =
[|(5, 1, 2, 3, 5); (7, 1, 2, 3, 7); (7, 1, 4, 5, 7); (9, 1, 4, 5, 9);
(9, 1, 6, 7, 9); (11, 1, 6, 7, 11); (11, 1, 8, 9, 11); (13, 1, 8, 9, 13);
(13, 1, 10, 11, 13); (15, 1, 10, 11, 15); (15, 1, 12, 13, 15);
(17, 1, 12, 13, 17); (17, 1, 14, 15, 17); (19, 1, 14, 15, 19);
(19, 1, 16, 17, 19)|]
Using the standard Rx workflow builder, you can create a function history that handles your example use case:
let history (io:IObservable<_>) =
io.Scan(new List<_>(), (fun l t -> l.Add t; l)).Distinct()
let io = new Subject<int>()
let newio = rx { let! history = history io
let! even = io.Where(fun v -> v % 2 = 0)
let! next = io.Take 1
let! odd = io.Where(fun v -> v % 2 = 1).Take 2
yield (history.Last(), history.[0], even, next, odd) }
newio.Subscribe(printfn "%O") |> ignore
for i = 1 to 20 do
io.OnNext i
Extending that to provide history length limits should be trivial. Was there a specific reason you need to define your own type/builder, or was doing that just a means to attain something like this?
Here's an example with combinators. You just have to define the observable outside the rx block. You could get history to work differently with immutable histories rather than a persistent list, so whatever fits your needs.
let history (io:IObservable<_>) =
io.Scan(new List<_>(), (fun l t -> l.Add t; l))
let newest (hist:'a List) = hist.Last()
let extract (ioHist:'a List IObservable) = ioHist.Select newest
let take (i:int) (ioHist: 'a List IObservable) = ioHist.Take i
let where (f: 'a -> bool) (ioHist: 'a List IObservable) = ioHist.Where(fun hist -> f(newest hist))
let io = new Subject<int>()
let history1 = history io
let newio =
rx { let! hist = history1.Distinct()
let! even = extract (history1 |> where (fun v -> v % 2 = 0))
let! next = extract (history1 |> take 1)
let! odd = extract (history1 |> where (fun v -> v % 2 = 1) |> take 2)
yield (hist.Last(), hist.[0], even, next, odd) }
You can use Observable.Buffer to do this already.
Sorry for the C# my F# hat is not thinking today.
IObservable<int> source = ...
IOBservable<IList<int>> buffered = source.Buffer(5,1)
will create you a stream of lists.
Or try to use buffer in LINQ which is more like F# query expressions
Console.WriteLine ("START");
var source = new List<int> () { 1, 2, 3, 4, 5 }.ToObservable ();
// LINQ C#'s Monad sugar
var r =
from buffer in source.Buffer (3, 1)
from x in buffer
from y in buffer
select new { x,y};
r.Subscribe (o=>Console.WriteLine (o.x + " " + o.y));
Console.WriteLine ("END");
Note from in LINQ is exactly/almost the same as let! in an f# query expression. The result is below. Also note how I am using buffer later in the expression just like you could in an f# query expression.
START
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
2 2
2 3
2 4
3 2
3 3
3 4
4 2
4 3
4 4
3 3
3 4
3 5
4 3
4 4
4 5
5 3
5 4
5 5
4 4
4 5
5 4
5 5
5 5
END
Sorry, my F# is extremely rusty, but perhaps you are looking for the Scan operator. It will push values to an accumulator as the source produces them and then you can use this accumulator to produce the next value for your projection.
Here (in C#, apologies) we take a sequence of [0..10] which produces these value 100ms apart, and we return a running Sum.
var source = Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(10);
source.Scan(
new List<long>(), //Seed value
(acc, value)=> //Accumulator function
{
acc.Add(value);
return acc;
}
)
.Select(accumate=>accumate.Sum())
which produces the values [0,1,3,6,10,15,21,28,36,45] 100ms apart.
I would think with this tool you can manage your History of values (by adding them to a history/accumulator) and then using this History in the Select to project the value that is appropriate.
I'm new to F# and I'm curious if this can still be optimized further. I am not particularly sure if I've done this correctly as well. I'm curious particularly on the last line as it looks really long and hideous.
I've searched over google, but only Roman Numeral to Number solutions only show up, so I'm having a hard time comparing.
type RomanDigit = I | IV | V | IX
let rec romanNumeral number =
let values = [ 9; 5; 4; 1 ]
let capture number values =
values
|> Seq.find ( fun x -> number >= x )
let toRomanDigit x =
match x with
| 9 -> IX
| 5 -> V
| 4 -> IV
| 1 -> I
match number with
| 0 -> []
| int -> Seq.toList ( Seq.concat [ [ toRomanDigit ( capture number values ) ]; romanNumeral ( number - ( capture number values ) ) ] )
Thanks for anyone who can help with this problem.
A slightly shorter way of recursively finding the largest digit representation that can be subtracted from the value (using List.find):
let units =
[1000, "M"
900, "CM"
500, "D"
400, "CD"
100, "C"
90, "XC"
50, "L"
40, "XL"
10, "X"
9, "IX"
5, "V"
4, "IV"
1, "I"]
let rec toRomanNumeral = function
| 0 -> ""
| n ->
let x, s = units |> List.find (fun (x,s) -> x <= n)
s + toRomanNumeral (n-x)
If I had to use a Discriminated Union to represent the roman letters I would not include IV and IX.
type RomanDigit = I|V|X
let numberToRoman n =
let (r, diff) =
if n > 8 then [X], n - 10
elif n > 3 then [V], n - 5
else [], n
if diff < 0 then I::r
else r # (List.replicate diff I)
Then, based in this solution you can go further and extend it to all numbers.
Here's my first attempt, using fold and partial application:
type RomanDigit = I|V|X|L|C|D|M
let numberToRoman n i v x =
let (r, diff) =
if n > 8 then [x], n - 10
elif n > 3 then [v], n - 5
else [], n
if diff < 0 then i::r
else r # (List.replicate diff i)
let allDigits (n:int) =
let (_, f) =
[(I,V); (X,L); (C,D)]
|> List.fold (fun (n, f) (i, v) ->
(n / 10, fun x -> (numberToRoman (n % 10) i v x) # f i)) (n, (fun _ -> []))
f M
Here's a tail-recursive version of #Philip Trelford's answer:
let toRomanNumeral n =
let rec iter acc n =
match n with
| 0 -> acc
| n ->
let x, s = units |> List.find (fun (x, _) -> x <= n)
iter (acc + s) (n-x)
iter "" n
#light
let a1 = [| (1, 1); (2, 1); (3, 1) |]
let a2 = [| (1, 1); (2, 3); (3, 1) |]
let aa = Array.zip a1 a2
|> Array.filter(fun (x, y) -> x <> y)
I want to write a function to do this: it will return the different tuple from two arrays, but I also want to return the index of the different tuple in the second array and the corresponding tuple in the second array. (My code did not work totally yet!)
For my above example, I want to return: 1 and (2, 3)
Another example:
let a1 = [| (1, 1); (2, 1); (3, 1); (4, 1) |]
let a2 = [| (1, 1); (2, 3); (3, 1); (4, 2) |]
I want to return: 1 and (2, 3); 3 and (4, 2)
If you have any idea, please show me your code.
Besides, I am not used to the new place for F#, the format makes me feel difficult to find a good place to post my questions, therefore, I still post my question here.
let a1 = [| (1, 1); (2, 1); (3, 1) |]
let a2 = [| (1, 1); (2, 3); (3, 1) |]
let diff =
(a1, a2)
||> Array.mapi2(fun i t1 t2 -> (i, t1, t2))
|> Array.choose(fun (i, a, b) -> if a <> b then Some (i, b) else None)
Here's one way to do it:
let diff a b =
let s = Set.ofSeq a
b
|> Seq.mapi (fun i x -> i, x)
|> Seq.filter (fun (_, x) -> not (Set.contains x s))
Example
let a1 = [| (1, 1); (2, 1); (3, 1) |]
let a2 = [| (1, 1); (2, 3); (3, 1) |]
diff a1 a2 //output: seq [(1, (2, 3))]
This works for any collection (list, array, seq<_>, set, etc) and the sequences may be of different lengths. If you know you'll always be using arrays of equal length, you can optimize accordingly (see desco's answer).
let diff (a:(int * int)[]) b =
b
|> Array.mapi (fun i tp -> if a.[i] <> tp then (i, tp) else (-1, tp))
|> Array.filter (fun (x, _) -> x >= 0)
DEMO
> diff a1 a2;;
val it : (int * (int * int)) [] = [|1, (2, 3)); (3, (4, 2))|]