Promixity in collection












0














Original Question



I want to use F# to find the proximity of consonants to vowels in a collection of words. So for example in the word "top" T is (-1: 1) from a vowel and P is (1: 1) from the vowel.



The first number in the pair is the position and the second number is the number of times it's in that position, relative to the nearest vowel.



In "consonants", C is (-1:1), N is (1: 3) , (-2: 1), (-1, 1), S is (2: 1), (-1:1),(3: 1) and T is (2: 1).



I suspect that I have to use a combination of groupBy, findIndex and countBy.



type ConsonantPos = { Name: string
BeforeVowel: int
AfterVowel: int }

let isVowel (x:string) =
List.contains x ["a";"e"; "i"; "o"; "u"]

let consonantPosVsVowel x lst =
let rec getConsonanatPos x beforeVowel afterVowel currentPos lst =
match lst with
| -> {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
| h::t ->
if isVowel h then
{Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
else
getConsonanatPos x (beforeVowel - 1) (afterVowel + 1) (currentPos + 1) t

getConsonanatPos x 0 0 0 lst


["b"; "a"; "c"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -1; AfterVowel = 1;}
["b"; "c"; "d"; "e"; "f"; "g"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -3; AfterVowel = 3;}


Revised Solution



As of 21/11/2018 both suggestions worked and worked well for the problem as I orginally specified.



Of course this question was just a part of the program that I was writing. As I have extended the program and explored the data, BEEP, one response proved easier to reuse: that is the one I have marked as the answer.



My problem, as it turned out, was my lack of understanding of and my inability to use collections.










share|improve this question
























  • Can you show us what you've tried already?
    – Ciaran_McCarthy
    Nov 19 '18 at 19:46










  • I am trying things as I go. I hope that I'll work it out.
    – Jack Chidley
    Nov 19 '18 at 20:07










  • In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
    – kaefer
    Nov 20 '18 at 18:21












  • When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
    – Jack Chidley
    Nov 21 '18 at 7:13


















0














Original Question



I want to use F# to find the proximity of consonants to vowels in a collection of words. So for example in the word "top" T is (-1: 1) from a vowel and P is (1: 1) from the vowel.



The first number in the pair is the position and the second number is the number of times it's in that position, relative to the nearest vowel.



In "consonants", C is (-1:1), N is (1: 3) , (-2: 1), (-1, 1), S is (2: 1), (-1:1),(3: 1) and T is (2: 1).



I suspect that I have to use a combination of groupBy, findIndex and countBy.



type ConsonantPos = { Name: string
BeforeVowel: int
AfterVowel: int }

let isVowel (x:string) =
List.contains x ["a";"e"; "i"; "o"; "u"]

let consonantPosVsVowel x lst =
let rec getConsonanatPos x beforeVowel afterVowel currentPos lst =
match lst with
| -> {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
| h::t ->
if isVowel h then
{Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
else
getConsonanatPos x (beforeVowel - 1) (afterVowel + 1) (currentPos + 1) t

getConsonanatPos x 0 0 0 lst


["b"; "a"; "c"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -1; AfterVowel = 1;}
["b"; "c"; "d"; "e"; "f"; "g"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -3; AfterVowel = 3;}


Revised Solution



As of 21/11/2018 both suggestions worked and worked well for the problem as I orginally specified.



Of course this question was just a part of the program that I was writing. As I have extended the program and explored the data, BEEP, one response proved easier to reuse: that is the one I have marked as the answer.



My problem, as it turned out, was my lack of understanding of and my inability to use collections.










share|improve this question
























  • Can you show us what you've tried already?
    – Ciaran_McCarthy
    Nov 19 '18 at 19:46










  • I am trying things as I go. I hope that I'll work it out.
    – Jack Chidley
    Nov 19 '18 at 20:07










  • In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
    – kaefer
    Nov 20 '18 at 18:21












  • When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
    – Jack Chidley
    Nov 21 '18 at 7:13
















0












0








0







Original Question



I want to use F# to find the proximity of consonants to vowels in a collection of words. So for example in the word "top" T is (-1: 1) from a vowel and P is (1: 1) from the vowel.



The first number in the pair is the position and the second number is the number of times it's in that position, relative to the nearest vowel.



In "consonants", C is (-1:1), N is (1: 3) , (-2: 1), (-1, 1), S is (2: 1), (-1:1),(3: 1) and T is (2: 1).



I suspect that I have to use a combination of groupBy, findIndex and countBy.



type ConsonantPos = { Name: string
BeforeVowel: int
AfterVowel: int }

let isVowel (x:string) =
List.contains x ["a";"e"; "i"; "o"; "u"]

let consonantPosVsVowel x lst =
let rec getConsonanatPos x beforeVowel afterVowel currentPos lst =
match lst with
| -> {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
| h::t ->
if isVowel h then
{Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
else
getConsonanatPos x (beforeVowel - 1) (afterVowel + 1) (currentPos + 1) t

getConsonanatPos x 0 0 0 lst


["b"; "a"; "c"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -1; AfterVowel = 1;}
["b"; "c"; "d"; "e"; "f"; "g"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -3; AfterVowel = 3;}


Revised Solution



As of 21/11/2018 both suggestions worked and worked well for the problem as I orginally specified.



Of course this question was just a part of the program that I was writing. As I have extended the program and explored the data, BEEP, one response proved easier to reuse: that is the one I have marked as the answer.



My problem, as it turned out, was my lack of understanding of and my inability to use collections.










share|improve this question















Original Question



I want to use F# to find the proximity of consonants to vowels in a collection of words. So for example in the word "top" T is (-1: 1) from a vowel and P is (1: 1) from the vowel.



The first number in the pair is the position and the second number is the number of times it's in that position, relative to the nearest vowel.



In "consonants", C is (-1:1), N is (1: 3) , (-2: 1), (-1, 1), S is (2: 1), (-1:1),(3: 1) and T is (2: 1).



I suspect that I have to use a combination of groupBy, findIndex and countBy.



type ConsonantPos = { Name: string
BeforeVowel: int
AfterVowel: int }

let isVowel (x:string) =
List.contains x ["a";"e"; "i"; "o"; "u"]

let consonantPosVsVowel x lst =
let rec getConsonanatPos x beforeVowel afterVowel currentPos lst =
match lst with
| -> {Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
| h::t ->
if isVowel h then
{Name = x; BeforeVowel = beforeVowel; AfterVowel = afterVowel}
else
getConsonanatPos x (beforeVowel - 1) (afterVowel + 1) (currentPos + 1) t

getConsonanatPos x 0 0 0 lst


["b"; "a"; "c"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -1; AfterVowel = 1;}
["b"; "c"; "d"; "e"; "f"; "g"] |> consonantPosVsVowel "b"
// val it : ConsonantPos = {Name = "b"; BeforeVowel = -3; AfterVowel = 3;}


Revised Solution



As of 21/11/2018 both suggestions worked and worked well for the problem as I orginally specified.



Of course this question was just a part of the program that I was writing. As I have extended the program and explored the data, BEEP, one response proved easier to reuse: that is the one I have marked as the answer.



My problem, as it turned out, was my lack of understanding of and my inability to use collections.







f#






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 11:06







Jack Chidley

















asked Nov 19 '18 at 19:12









Jack ChidleyJack Chidley

699




699












  • Can you show us what you've tried already?
    – Ciaran_McCarthy
    Nov 19 '18 at 19:46










  • I am trying things as I go. I hope that I'll work it out.
    – Jack Chidley
    Nov 19 '18 at 20:07










  • In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
    – kaefer
    Nov 20 '18 at 18:21












  • When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
    – Jack Chidley
    Nov 21 '18 at 7:13




















  • Can you show us what you've tried already?
    – Ciaran_McCarthy
    Nov 19 '18 at 19:46










  • I am trying things as I go. I hope that I'll work it out.
    – Jack Chidley
    Nov 19 '18 at 20:07










  • In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
    – kaefer
    Nov 20 '18 at 18:21












  • When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
    – Jack Chidley
    Nov 21 '18 at 7:13


















Can you show us what you've tried already?
– Ciaran_McCarthy
Nov 19 '18 at 19:46




Can you show us what you've tried already?
– Ciaran_McCarthy
Nov 19 '18 at 19:46












I am trying things as I go. I hope that I'll work it out.
– Jack Chidley
Nov 19 '18 at 20:07




I am trying things as I go. I hope that I'll work it out.
– Jack Chidley
Nov 19 '18 at 20:07












In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
– kaefer
Nov 20 '18 at 18:21






In your edit Revised Solution, you did change the rules somewhat, so that they do not really match the Original Question any more. You are now also determining the distance of consonants to word boundaries. But this is fine, I'm happy that you found whatever was needed to float your boat.
– kaefer
Nov 20 '18 at 18:21














When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
– Jack Chidley
Nov 21 '18 at 7:13






When I started looking at the problem, I had no idea where to start. As you stated, my actual needs turned out to be slightly different from what I wrote in the question. That is why I left the original question unchanged. Thanks to you, kaefer, and AMieres not only did I manage to solve my real problem but I also learnt a lot. Before I posted the question I had tried, for several hours, to find a solution. It's astonishing to me that two people worked out, and coded, a solution to my original problem in under an hour from posting it! I am so grateful: I love the Stack community
– Jack Chidley
Nov 21 '18 at 7:13














2 Answers
2






active

oldest

votes


















1














Here's a slightly different approach, which breaks down the task differently.




  • Map the element to itself with its tail (negative distance, forward) and heads
    (positive, backward). This is done with a recursive function and two
    accumulators

  • Filter the resulting list for elements not being vowels

  • Map it to pairs of options representing negative and positive distances, with
    another recursive function, and collect these pairs into a flat list
    again while transposing their values

  • Group this list by the elements, and map the result to a tuple of distance and number of occurance




let genTail2 xss =
let rec aux accl accr = function
| -> List.rev accr
| x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
aux xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
let rec aux n i = function
| -> None
| y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
aux -1 -1 ls, aux 1 1 rs
// val dist2 :
// pred:('a -> bool) ->
// x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None ->
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")





share|improve this answer























  • Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
    – Jack Chidley
    Nov 19 '18 at 22:40










  • This response proved to be the flexible, easy to understand and easy to reuse.
    – Jack Chidley
    Nov 21 '18 at 11:14



















2














Try this:



let isVowel (x:char) =
List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
let vowelsp, consonants =
word
|> Seq.mapi(fun i c-> c,i )
|> Seq.toArray
|> Array.partition (fst >> isVowel)
let vowels = vowelsp |> Array.map snd
consonants
|> Seq.collect (fun (c,i) ->
match vowels |> Array.tryFindIndex ((<) i) with
| None -> [ vowels.Length - 1 ]
| Some j -> [ j - 1 ; j ]
|> Seq.choose (fun j ->
if j < 0 then None else
Some(c, i - vowels.[j])
)
)
|> Seq.countBy id
|> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
|> Seq.groupBy fst
|> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
|> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")





share|improve this answer























  • Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
    – Jack Chidley
    Nov 19 '18 at 20:48











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381162%2fpromixity-in-collection%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Here's a slightly different approach, which breaks down the task differently.




  • Map the element to itself with its tail (negative distance, forward) and heads
    (positive, backward). This is done with a recursive function and two
    accumulators

  • Filter the resulting list for elements not being vowels

  • Map it to pairs of options representing negative and positive distances, with
    another recursive function, and collect these pairs into a flat list
    again while transposing their values

  • Group this list by the elements, and map the result to a tuple of distance and number of occurance




let genTail2 xss =
let rec aux accl accr = function
| -> List.rev accr
| x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
aux xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
let rec aux n i = function
| -> None
| y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
aux -1 -1 ls, aux 1 1 rs
// val dist2 :
// pred:('a -> bool) ->
// x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None ->
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")





share|improve this answer























  • Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
    – Jack Chidley
    Nov 19 '18 at 22:40










  • This response proved to be the flexible, easy to understand and easy to reuse.
    – Jack Chidley
    Nov 21 '18 at 11:14
















1














Here's a slightly different approach, which breaks down the task differently.




  • Map the element to itself with its tail (negative distance, forward) and heads
    (positive, backward). This is done with a recursive function and two
    accumulators

  • Filter the resulting list for elements not being vowels

  • Map it to pairs of options representing negative and positive distances, with
    another recursive function, and collect these pairs into a flat list
    again while transposing their values

  • Group this list by the elements, and map the result to a tuple of distance and number of occurance




let genTail2 xss =
let rec aux accl accr = function
| -> List.rev accr
| x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
aux xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
let rec aux n i = function
| -> None
| y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
aux -1 -1 ls, aux 1 1 rs
// val dist2 :
// pred:('a -> bool) ->
// x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None ->
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")





share|improve this answer























  • Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
    – Jack Chidley
    Nov 19 '18 at 22:40










  • This response proved to be the flexible, easy to understand and easy to reuse.
    – Jack Chidley
    Nov 21 '18 at 11:14














1












1








1






Here's a slightly different approach, which breaks down the task differently.




  • Map the element to itself with its tail (negative distance, forward) and heads
    (positive, backward). This is done with a recursive function and two
    accumulators

  • Filter the resulting list for elements not being vowels

  • Map it to pairs of options representing negative and positive distances, with
    another recursive function, and collect these pairs into a flat list
    again while transposing their values

  • Group this list by the elements, and map the result to a tuple of distance and number of occurance




let genTail2 xss =
let rec aux accl accr = function
| -> List.rev accr
| x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
aux xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
let rec aux n i = function
| -> None
| y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
aux -1 -1 ls, aux 1 1 rs
// val dist2 :
// pred:('a -> bool) ->
// x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None ->
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")





share|improve this answer














Here's a slightly different approach, which breaks down the task differently.




  • Map the element to itself with its tail (negative distance, forward) and heads
    (positive, backward). This is done with a recursive function and two
    accumulators

  • Filter the resulting list for elements not being vowels

  • Map it to pairs of options representing negative and positive distances, with
    another recursive function, and collect these pairs into a flat list
    again while transposing their values

  • Group this list by the elements, and map the result to a tuple of distance and number of occurance




let genTail2 xss =
let rec aux accl accr = function
| -> List.rev accr
| x::xs -> aux (x::accl) ((x, (xs, accl))::accr) xs
aux xss
// val genTail2 : xss:'a list -> ('a * ('a list * 'a list)) list

let dist2 pred (x, (ls, rs)) =
let rec aux n i = function
| -> None
| y::ys -> if pred y then Some(x, n) else aux (n + i) i ys
aux -1 -1 ls, aux 1 1 rs
// val dist2 :
// pred:('a -> bool) ->
// x:'b * ('a list * 'a list) -> ('b * int) option * ('b * int) option

let tuple2List = function
| None, None ->
| Some x, None | None, Some x -> [x]
| Some x, Some y -> [y; x]
// val tuple2List : 'a option * 'a option -> 'a list

let isVowel = ResizeArray['a';'e';'i';'o';'u'].Contains
// val isVowel : (char -> bool)

"consonants"
|> fun s -> s.ToLower()
|> Seq.toList
|> genTail2
|> List.filter (fst >> isVowel >> not)
|> List.collect (dist2 isVowel >> tuple2List)
|> Seq.groupBy fst
|> Seq.map (fun (x, xs) -> x, Seq.countBy snd xs)
|> Seq.iter (printfn "%A")






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 19 '18 at 21:56

























answered Nov 19 '18 at 21:44









kaeferkaefer

3,2651715




3,2651715












  • Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
    – Jack Chidley
    Nov 19 '18 at 22:40










  • This response proved to be the flexible, easy to understand and easy to reuse.
    – Jack Chidley
    Nov 21 '18 at 11:14


















  • Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
    – Jack Chidley
    Nov 19 '18 at 22:40










  • This response proved to be the flexible, easy to understand and easy to reuse.
    – Jack Chidley
    Nov 21 '18 at 11:14
















Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
– Jack Chidley
Nov 19 '18 at 22:40




Wow, this looks like it works too! I am not surprised that I couldn't figure it out myself.
– Jack Chidley
Nov 19 '18 at 22:40












This response proved to be the flexible, easy to understand and easy to reuse.
– Jack Chidley
Nov 21 '18 at 11:14




This response proved to be the flexible, easy to understand and easy to reuse.
– Jack Chidley
Nov 21 '18 at 11:14













2














Try this:



let isVowel (x:char) =
List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
let vowelsp, consonants =
word
|> Seq.mapi(fun i c-> c,i )
|> Seq.toArray
|> Array.partition (fst >> isVowel)
let vowels = vowelsp |> Array.map snd
consonants
|> Seq.collect (fun (c,i) ->
match vowels |> Array.tryFindIndex ((<) i) with
| None -> [ vowels.Length - 1 ]
| Some j -> [ j - 1 ; j ]
|> Seq.choose (fun j ->
if j < 0 then None else
Some(c, i - vowels.[j])
)
)
|> Seq.countBy id
|> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
|> Seq.groupBy fst
|> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
|> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")





share|improve this answer























  • Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
    – Jack Chidley
    Nov 19 '18 at 20:48
















2














Try this:



let isVowel (x:char) =
List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
let vowelsp, consonants =
word
|> Seq.mapi(fun i c-> c,i )
|> Seq.toArray
|> Array.partition (fst >> isVowel)
let vowels = vowelsp |> Array.map snd
consonants
|> Seq.collect (fun (c,i) ->
match vowels |> Array.tryFindIndex ((<) i) with
| None -> [ vowels.Length - 1 ]
| Some j -> [ j - 1 ; j ]
|> Seq.choose (fun j ->
if j < 0 then None else
Some(c, i - vowels.[j])
)
)
|> Seq.countBy id
|> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
|> Seq.groupBy fst
|> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
|> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")





share|improve this answer























  • Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
    – Jack Chidley
    Nov 19 '18 at 20:48














2












2








2






Try this:



let isVowel (x:char) =
List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
let vowelsp, consonants =
word
|> Seq.mapi(fun i c-> c,i )
|> Seq.toArray
|> Array.partition (fst >> isVowel)
let vowels = vowelsp |> Array.map snd
consonants
|> Seq.collect (fun (c,i) ->
match vowels |> Array.tryFindIndex ((<) i) with
| None -> [ vowels.Length - 1 ]
| Some j -> [ j - 1 ; j ]
|> Seq.choose (fun j ->
if j < 0 then None else
Some(c, i - vowels.[j])
)
)
|> Seq.countBy id
|> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
|> Seq.groupBy fst
|> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
|> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")





share|improve this answer














Try this:



let isVowel (x:char) =
List.contains x ['a';'e'; 'i'; 'o'; 'u']

let countConsonants (word:string) =
let vowelsp, consonants =
word
|> Seq.mapi(fun i c-> c,i )
|> Seq.toArray
|> Array.partition (fst >> isVowel)
let vowels = vowelsp |> Array.map snd
consonants
|> Seq.collect (fun (c,i) ->
match vowels |> Array.tryFindIndex ((<) i) with
| None -> [ vowels.Length - 1 ]
| Some j -> [ j - 1 ; j ]
|> Seq.choose (fun j ->
if j < 0 then None else
Some(c, i - vowels.[j])
)
)
|> Seq.countBy id
|> Seq.map (fun ((l,p), c) -> (l,(p, c)) )
|> Seq.groupBy fst
|> Seq.map (fun (l, s) -> l, s |> Seq.map snd |> Seq.toArray)
|> Seq.toArray

"consonants"
|> countConsonants
|> Seq.iter (printfn "%A")






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 19 '18 at 20:59

























answered Nov 19 '18 at 20:41









AMieresAMieres

2,415511




2,415511












  • Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
    – Jack Chidley
    Nov 19 '18 at 20:48


















  • Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
    – Jack Chidley
    Nov 19 '18 at 20:48
















Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
– Jack Chidley
Nov 19 '18 at 20:48




Oh, that looks like it might work! I need to check it out and watch a film with the wife... could be a while
– Jack Chidley
Nov 19 '18 at 20:48


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381162%2fpromixity-in-collection%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

ts Property 'filter' does not exist on type '{}'

mat-slide-toggle shouldn't change it's state when I click cancel in confirmation window