my task is to parse that list
(100 30 5 . 50 6)
to number 135.56
format of input list is always the same
and I've wrote:
(reduce
'string-concat
(mapcar
(lambda (x) (remove #\0 x))
(mapcar
'write-to-string
l
)
)
)
and output I've "135|.|56"
and then read-from-string does'n read it, so...
have You any idea how I can do this parsing?
using or not code above
Your approach does not look particular robust. Also it is kind of difficult to understand what the input list is. Is the dot a symbol, like in |.|? The vertical bars are escaping the name, so that it does not collide with the built-in usage of the dot character in Lisp. It is used in dotted pairs, which stand for cons cells: (a . b).
If it is a symbol, then you can write the symbol without escaping to a string. First, with escaping:
CL-USER 5 > (write-to-string '|.|)
"\\."
Next, without:
CL-USER 6 > (princ-to-string '|.|)
"."
Your list (100 30 5 . 50 6) isn't a valid list structure in Common Lisp. A "dotted pair" must have only one element after the dot. If you want to know more about it, look at your favorite Common Lisp Book how lists are build from cons cells. (For example Peter Seibels "Practical Common Lisp")
So you cannot parse this string as a list as such - you need to have a pre-processing step.
(defun pre-processing (str)
(let ((idx (position #\. str)))
(list (read-from-string (concatenate 'string (subseq str 0 idx) ")"))
(read-from-string (concatenate 'string "(" (subseq str (1+ idx)))))))
This function splits your string in two lists that you can process the way you want to.
CL-USER 1 > (pre-processing "(100 30 5 . 50 6)")
((100 30 5) (50 6))
Related
We try to change the way maxima translates multiplication when converting to tex.
By default maxima gives a space: \,
We changed this to our own latex macro that looks like a space, but in that way we conserve the sementical meaning which makes it easier to convert the latex back to maxima.
:lisp (setf (get 'mtimes 'texsym) '("\\invisibletimes "));
However, we have one problem, and that is when we put simplification on. We use this for generating steps in the explanation of a solution. For example:
tex1(block([simp: false], 2*3));
Of course when multiplying numbers we can want an explicit multiplication (\cdot).
So we would like it that if both arguments of the multiplication are numbers, that we then have a \cdot when translating to tex.
Is that possible?
Yes, if there is a function named by the TEX property, that function is called to process an expression. The function named by TEX takes 3 arguments, namely an expression with the same operator to which the TEX property is attached, stuff to the left, and stuff to the right, and the TEX function returns a list of strings which are the bits of TeX which should be output.
You can say :lisp (trace tex-mtimes) to see how that works. You can see the functions attached to MTIMES or other operators by saying :lisp (symbol-plist 'mtimes) or in general :lisp (symbol-plist 'mfoo) for another MFOO operator.
So if you replace TEX-MTIMES (by :lisp (setf (get 'mtimes 'tex) 'my-tex-mtimes)) by some other function, then you can control the output to a greater extent. Here is an outline of a suitable function for your purpose:
(defun my-tex-mtimes (e l r)
(if $simp
(tex-nary e l r) ;; punt to default handler
(tex-mtimes-special-case e l r)))
You can make TEX-MTIMES-SPECIAL-CASE as complicated as you want. I assume that you can carry out the Lisp programming for that. The simplest thing to try, perhaps a point of departure for further efforts, is to just temporarily replace TEXSYM with \cdot. Something like:
(defun tex-mtimes-special-case (e l r)
(let ((prev-texsym (get 'mtimes 'texsym)))
(prog2 (setf (get 'mtimes 'texsym) (list "\\cdot "))
(tex-nary e l r)
(setf (get 'mtimes 'texsym) prev-texsym))))
I would like to be able to input a sequence of integers on one line, such as:
97, 128, 125, 17, 2
and have the Haskell program convert the input into a list of integers, such as:
[97, 128, 135, 17, 2]
so that I can do some math operations like zipWith(ing) the list with another list of integers. Having trouble with this. I tried using the read and words functions but I wasn't able to achieve the expected result. Any ideas?
One possible (again, quick'n'dirty) solution is to use read with the instance defined for lists, which expects strings in the format [item1, item2, item3...]:
convert :: String -> [Int]
convert s = read $ "[" ++ s ++ "]"
A more robust solution would be parsing with filter or similar (as shown in the other answer) or using a parsing library to do the job properly.
The problem with only using words is that the comma (,) will still be included.
A quick-and-dirty hack is probably to first map all characters instead of digits to a space:
import Data.Char(isDigit)
cnv x | isDigit x = x
| otherwise = ' '
and then use:
map read . words . map cnv :: Read b => [Char] -> [b]
demo
*Main> ((map read . words . map cnv) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]
A potential problem is of course that you omit [A-z] characters, etc. Furthermore this approach is not the most efficient.
An advantage is that by using read all items that can be read are still candidates to process the stream of "words".
Why not filtering?
One can also use a filter evidently to obtain for instance only spaces and digits. For instance
map read . words . filter (\x -> isDigit x || isSpace x)
A potential problem is that it is possible that the numbers are not separated by spaces ( ), but only by commas (,), semi-colons (;), etc. Working with the above expression generates the correct result:
(map read . words . filter (\x -> isDigit x || isSpace x)) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]
but
(map read . words . filter (\x -> isDigit x || isSpace x)) "97,128,125,17,2" :: [Int]
[97128125172]
doesn't.
The task you're specifying falls under the category of textual parsing. When facing such a problem the safe bet is to approach it with either the "parsec" or the "attoparsec" library. Those libraries provide APIs which abstract over parsing in a safe and composable (hence scalable) way.
Here's how you'd write the "attoparsec" parser for your task:
listOfInts :: Parser [Int]
listOfInts =
sepBy decimal separator
where
separator =
skipSpace *> char ',' *> skipSpace
Note that the provided implementation already allows you to parse a not well formed input, where the separator might have multiple or no spaces before and after the comma. Also note how simple it is to express this already complicated condition using such a parser.
Thank you all for your help. For my application, this seems to work well:
myInput <- getLine
123 23 345 23
(map read . words) myInput::[Int]
I was having a little trouble understanding why the parenthesis go where they do, but this seems to work also:
myInput <- getLine
234 34 235 465 34
map read $ words myInput::[Int]
Since I'm just using spaces to separate the numbers, I don't have to use the filter, but thanks for posting it because now I understand the syntax better.
Don
I'm learning Erlang and I was asking myself what is the best way to turn the time() output into a formatted time string (HH:MM:SS).
The code I came up with is:
my_time() ->
{H, M, S} = time(),
integer_to_list(H) ++ ":" ++ integer_to_list(M) ++ ":" ++ integer_to_list(S).
This code won't do the trick exactly as it won't pad with zeros the minutes or seconds. It also uses the ++ operator to concatenate lists which isn't recommended.
What is the correct way of implementing this trivial task in Erlang?
A correct, easy-to-understand implementation uses format (which is like printf):
my_time() ->
{H, M, S} = time(),
io_lib:format('~2..0b:~2..0b:~2..0b', [H, M, S]).
~2..0b is a placeholder for an integer to be printed in base 10, taking up at least 2 characters, and padded on the left with the character 0.
References:
http://www.erlang.org/doc/man/io_lib.html#format-2 (the function that you're calling)
http://www.erlang.org/doc/man/io.html#fwrite-1 (the place where the format is documented)
You should only worry about performance if you're calling your function in a tight loop, and if profiling benchmarks show that your function is actually a bottleneck.
I don't know why you think concatenating list with length 8 can be any problem but if you want be really fast you can do:
my_time() ->
{H, M, S} = time(),
[$0 + H div 10, $0 + H rem 10, $:, $0 + M div 10, $0 + M rem 10, $:, $0 + S div 10, $0 + S rem 10].
There are not correct ways, there are faster or slower, more or less memory consuming and more or less concise solutions.
Edit: If you like more concise but same performance:
-define(DEC(X), $0 + X div 10, $0 + X rem 10).
my_time() ->
{H, M, S} = time(),
[?DEC(H), $:, ?DEC(M), $:, ?DEC(S)].
I like Dave Harveys dh_date module. The only "fix" required is that format/2 only take now() or datetime(). Easily fixed as in the example below.
4> dh_date:format("H:i:s",{{0,0,0},time()}).
"07:23:58"
I found that there is a || in list manipulation. What does the || mean? Are there any examples about ||?
lists:sum([A*B || {A, B} <- Foo]).
It is used in List comprehensions. List comprehensions is a shorter way to create lists without having to use funs, maps or filters.
From Programming Erlang:
If we have a list L:
L = [1,2,3,4,5].
And we want to double every element, we can do:
lists:map(fun(X) -> 2*X end, L).
But with List comprehensions we can do:
[2*X || X <- L].
Nomenclature most likely comes from mathematical notion of sets, where || means "such that".
e.g. copied from Wikipedia
F = {n2 − 4 : n is an integer; and 0 ≤ n ≤ 19}
In this notation, the colon (":") means "such that", and the description can be interpreted as "F is the set of all numbers of the form n2 − 4, such that n is a whole number in the range from 0 to 19 inclusive." Sometimes the vertical bar ("|") is used instead of the colon.
Applying same thing to
lists:sum([A*B || {A, B} <- Foo]).
means:- generate A*B such that A and B belong to list of tuples "Foo"
Is it possible to implement a closure in Erlang?
For example, how would I translate this snippet from Scheme?
(define (make-adder n)
(lamdba (x) (+ x n)))
I've tried the following, but I'm clearly missing something.
make_adder(n) ->
fun (x) -> x + n end.
Compiling this gives the error
Warning: this expression will fail with a 'badarith' exception
You can't add atoms. Variables start with Capital Letters in erlang. words starting with lower case letters are atoms.
In other words your problem is not related to funs at all, you just need to capitalize your variable names.
make_adder(N) ->
fun (X) -> X + N end.
Variables start with Capital Letters in erlang.
words starting with lower case letters are atoms.