I was raking around on the net and found this problem and coded up a solution. Once we get at least 10 solutions I'll post mine and a link to where I found the problem.
Any language, any libraries (but declare them) allowed. Aim for clarity and conciseness. Assume the input is well formed. Mine is 5 lines of scheme code (6 if we include requiring a library). No calling an "answer" function that "you wrote already and put in an external lib" ;)
Consider the problem of turning a list consisting
of a mix between symbols and non-symbols into a
list of lists of the symbol and its following
non-symbols. That is:
Input: ({<symbol> <non-symbol>*} ... )
Output: ((<symbol> (<non-symbol>*)) ...)
Example: (a 1 2 3 b 4 5 c d 8 9 e)
-> ((a (1 2 3)) (b (4 5)) (c ()) (d (8 9)) (e ()))
Name:
Anonymous2009-12-13 1:09
One line of actual code does the job:
import Data.List (groupBy)
f :: (String -> Bool) -> [String] -> [[String]]
f isSymbol = groupBy (const $ not . isSymbol)
Given a predicate that determines whether a string is a symbol or not, ``f'' produces the desired function.
Example:
GHCi> -- We define a symbol to be a string that does not begin with a digit.
GHCi> -- For the sake of simplicity, all strings are assumed to be non-empty.
GHCi> let isSymbol = (`notElem` ['0'..'9']) . head
GHCi> -- Let's test it.
GHCi> (isSymbol "foo", isSymbol "3bar")
(True,False)
GHCi> -- Finally, we test f.
GHCi> f isSymbol ["a", "1", "2", "3", "b", "4", "5", "c", "d", "8", "9", "e"]
[["a","1","2","3"],["b","4","5"],["c"],["d","8","9"],["e"]]
Now, due to the fact that Haskell's lists are homogenous, the output format is slightly different from the one specified in >>1. We can alter f to return tuples instead:
f :: (String -> Bool) -> [String] -> [(String, [String])]
f isSymbol = map (\ (s : ns) -> (s, ns)) . groupBy (const $ not . isSymbol)
And of course, constraining this function to Strings is quite pointless. The same code will work with the more general type signature (a -> Bool) -> [a] -> [(a, [a])].
Name:
132009-12-13 2:59
Thanks >>41, your post gave me an idea on how to write this a lot more concisely:
(asdf:oos 'asdf:load-op :split-sequence)
(use-package :split-sequence)
I am sorry, I must have missed something obvious, but how do we know that '1' is not also a symbol? You need a symbol table to correctly solve this problem, it seems to me. It seems unspecified what, exactly, a symbol is.
>>45
OP already mentioned that he meant Lisp-like symbols:
1, "1" or '|1| are very different kinds of objects, one is the integer 1, the other is a string containg the character #\1, and the other is a symbol named by the string "1". Things may be slightly different in Scheme, but 1 and '1' are different things. OP's problems essentially boils down to grouping down objects given a predicate which separates the objects into 2 disjoint groups, the actual meaning of symbols or non-symbols is not as relevant, sadly, at least some half of the solutions are string-based, so they miss the point of the problem, and work with some limited amount of input.
Name:
Anonymous2009-12-13 21:13
This is my first non-trivial algorithm in F#. Gosh, this is hard.
let rec splitlist l along =
let rec gather l =
match l with
|[] -> []
|head::tail when (head<>along) -> head::(gather tail)
|head::tail -> []
match l with
|[] -> []
|head::tail when (head=along) -> (head::(gather tail))::(splitlist tail along)
|head::tail -> (splitlist tail along)
let separate l along=
(splitlist l along) |> Seq.map (fun x -> match x with |head::tail -> (head ,tail))