Im starting to program in Lisp and having an hard time with the Format function.
My objective is to print a list of integer sublists as N integers for line. For example:
'((1 2 3)
(4 5 6)
(7 8 9))
should be printed as
1 2 3
4 5 6
7 8 9
I tried using iteration in the format procedure, but I failed.
What I wrote was:
(format t "~{~S ~}" list)
But with this I get the sublists as "(1 2 3)" instead of "1 2 3", so i tried:
(format t "~:{ ~S ~}" list)
this time I got into the sublists but only printed the first element, so I stepped in and re-wrote the function to:
(format t "~:{ ~S ~S ~S ~}" list)
It works for sublists with 3 elements, but how can I make it work for n elements?
Thanks!
(format t "~{~%~{~A~^ ~}~}" '((1 2 3) (4 5 6) (7 8 9)))
prints
1 2 3
4 5 6
7 8 9
Related
I have built a long nested list having the following profile:
set my-list [A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]
I'd like to apply the meancommand to the fourth item of each nested lists, so in the example to
4 8 12
but without building a list in loop that would look like [4 8 12] (to save computing time).
Is it possible ?
using let comp mean (item i item 4 (my-list)) or let comp mean (item 4 (my-list)) aren't obviously working.
The answer would be useful to other part of the model that I'm building.
Thanks for your time.
The map primitive is very well suited for these sorts of calculations with lists. It allows you to perform a reporter separately for each part of a list and then returns the results as a new list.
let test-list [1 2 3]
show map [x -> x + 1] test-list
;> [2 3 4]
In your case, you would use map to cycle through your list of lists, and use the item primitive to extract the necessary number from each sublist (map [x -> item 4 x ] my-list). This then returns them as a list of which you can take the mean.
to check-mean-2
let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let my-mean mean map [x -> item 4 x ] my-list
print my-mean
end
EDIT: Although mine looks more efficient on first glance, Matteo's version actually runs quicker (at least on my machine)
globals [my-list]
to setup
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
end
to check-mean
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let the-sum 0
let i 0
while [i < length my-list] [
set the-sum (the-sum + item 4 (item i my-list))
set i i + 1
]
let my-mean the-sum / i
]
let the-timer timer ; ~0.207
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.210
end
to check-mean-2
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-mean mean map [x -> item 4 x ] my-list
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.235
end
ANOTHER EDIT: Finally two more versions using reduce instead of map. Version 3 is the fastest of them all but you should take notice of the fact that my-list has a 0 added to it in this version. This might make is slightly less conveniet for other purposes. You can also add this 0 to it during the calculation as seen in version 4, but that drives up the time again.
to check-mean-3
set my-list [0 ["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-sum reduce [ [x y] -> x + item 4 y] my-list
let my-mean my-sum / (length my-list - 1)
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.170
end
to check-mean-4
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let timer-list []
repeat 10 [
reset-timer
repeat 1000000 [
let my-new-list fput 0 my-list
let my-sum reduce [ [x y] -> x + item 4 y] my-new-list
let my-mean my-sum / (length my-list - 1)
]
let the-timer timer
show the-timer
set timer-list lput the-timer timer-list
]
show word "mean: " (mean timer-list) ; 0.226
end
First things first: did you mean to say that such nested list is built such as the one below?
set my-list [[A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]]
Note the extra pair of square brackets, that make this actually a list of lists. Even if that was the case, NetLogo wouldn't let you use that syntax:
Either because A, B and C are lacking quotation marks if you intend them to be strings;
Or because, if A, B and C are variables, NetLogo expects literal values (we can get around this problem by using (list ...) instead of []).
In the first case, it would have to be:
set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
In the second case, it would have to be:
set my-list (list (list a 1 2 3 4) (list b 5 6 7 8) (list c 9 10 11 12))
All of the above just to make sure we are all on the same page (in general, please make sure that the code you post in your question is valid for the language you are asking about. As you can see, it would save a lot of time and space!).
Anyway I imagine that what you come up with is something of this type:
[["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
I would use a while loop to iterate through the inner lists. You can create a local variable to keep track of the sum of the numbers you extract as you iterate through the inner lists, and then divide that sum by the number of times you extracted a number:
to check-mean
let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
let the-sum 0
let i 0
while [i < length my-list] [
set the-sum (the-sum + item 4 (item i my-list))
set i i + 1
]
print the-sum / i
end
From the answers above and adding a step in the procedure (mean and sd for groups of items having the same "region" in the list), here-below is my final code using map as the mean and sd are already calculated in a while-loop. Moreover, I assumed that calculating manually the standard deviation would create even more lists of list and complicate the code.
to create-successor-list
set successor-list map [inner-list -> (list inner-list 0 0 ) ] region-data
let i 0
while [i < length region-data] [
let current-item item i region-data
set temp-profitability-list (filter [current-inner-list -> (item 1 current-inner-list = current-item)] profitability-list )
set prof-mean mean map [x -> item 4 x ] temp-profitability-list
set prof-sd standard-deviation map [x -> item 4 x ] temp-profitability-list
set successor-list replace-item i successor-list (replace-item 1 item i successor-list (prof-mean))
set successor-list replace-item i successor-list (replace-item 2 item i successor-list (prof-sd))
set i i + 1
set temp-profitability-list [ ]
]
end
im making a solitaire game and to start off I'm making a function which provides either true or false if the given value on the card is valid as shown in the lists:
(define (card? val)
(cond
[(list? (member(car val) (1 2 3 4 5 6 7 #\J #\K #\Q))) #t]
[(list? (member(cdr val) (#\H #\S #\C #\D))) #t]
[else #f]))
so here, if i input (card? 7 #\C) then id want it print
#true
#true
any help would be appreciated
I tried to minimise the code as glennsl suggested. It turns out, I don't know how to read inputs from multiple lines in OCaml.
For example, pretend, stdin contains the following pattern
5
1 2 3 4 5
3
6 7 8
I need to read this and print to stdout. I'm using the "%d %d %d %d %d\n" format specifier as if I know the number of inputs is 5 in advance, just to illustrate my problem.
Now the following code fails with the same error Fatal error: exception End_of_file (I have tried to reproduce the same problem with fewer lines of code) if I uncomment the bottom part.
let number_of_inputs1 = read_int () in
let input_arr1 = Scanf.scanf "%d %d %d %d %d\n" (fun a b c d e -> [a]#[b]#[c]#[d]#[e]) in
let rec print_test_case inputs =
match inputs with
|[] ->(print_newline ();print_string "done test case"; print_newline ();)
|hd::tl -> (print_int hd; print_string " "; print_test_case tl)
in print_int number_of_inputs1; print_newline (); print_test_case input_arr1;
(*
let number_of_inputs2 = read_int () in
let input_arr2 = Scanf.scanf "%d %d %d\n" (fun a b c -> [a]#[b]#[c]) in
print_int number_of_inputs2; print_newline (); print_test_case input_arr2;
*)
It prints the following now,
5
1 2 3 4 5
done test case
I need to print something like
5
1 2 3 4 5
done test case
3
6 7 8
done test case
How should I read such formatted input in multiple lines from stdin correctly ?
The original problem I faced is what follows.
I have a problem where the number of test cases t is specified in the first line of the input. The t test cases follow. Each test case is comprised of two lines
line#1: number of inputs n, for this particular test case
line#2: the n input numbers separated by space
I need to do some computation for each test case. Let's assume I just need to print them back to the console with a message "done test case" after each test case output.
For example if the input was the following,
5
3
1 2 3
3
2 1 3
6
3 2 1 5 4 6
4
1 3 4 2
5
3 4 5 1 2
Observe that there are 5 test cases in this problem. The first test case for example, has 3 inputs 1 2 3, and the third one has 6, 3 2 1 5 4 6.
I need to print
1 2 3
done test case
2 1 3
done test case
3 2 1 5 4 6
done test case
1 3 4 2
done test case
3 4 5 1 2
done test case
So far, I have tried the following,
let test_cases = read_int () in (*read the number of test cases*)
let rec print_all_test_cases tc = (*define a function that will call the individual test cases*)
if (tc > 0) (*check if there are more test cases left*)
then
let num_of_inputs = read_int() in (*read the number of inputs*)
let rec read_inputs_for_test_case n arr = (*function to recursively read all inputs for the test case*)
if (n == 0)
then arr (*if everthing is read return the accumulated array*)
else
let i = Scanf.scanf "%d " (fun i -> i) in (*else read the input*)
read_inputs_for_test_case (n-1) (arr # [i]) (*recurse for the remaining inputs, accumulating current input to the argument*)
in
let rec print_test_case inputs = (*print inputs for the test case*)
match inputs with
|[] ->(print_newline ();print_string "done test case"; print_newline ();)
|hd::tl -> (print_int hd; print_string " "; print_test_case tl)
in
print_test_case (read_inputs_for_test_case num_of_inputs []); (*call to read and print inputs*)
print_all_test_cases (tc-1) (*recursively do the remaining test cases*)
else ()
in print_all_test_cases test_cases
It prints the following to stdout
1 2 3
done test case
and fails with the following error on stderr
Fatal error: exception End_of_file
How do read everything correctly and print as required ?
There is no error in your simplified code extract, uncommenting the second part should work if the stdin had the right data.
You should probably test your code with a fixed string data first:
let text = "5
1 2 3 4 5
3
6 7 8
"
let source = Scanf.Scanning.from_string text
let number_of_inputs1 = Scanf.bscanf source "%d\n" (fun n -> n)
let input_arr1 =
Scanf.bscanf source "%d %d %d %d %d\n" (fun a b c d e -> [a;b;c;d;e])
I want to get values from 2 series into one but it is not working:
I have 2 series:
a: [1 2 3]
b: [4 5 6 7]
I want to get all values in one list, so that I can access them as allv/1, allv/2... allv/7.
Following is not working since it makes a series of series and not series of values:
allv: [a b]
print allv ; => prints all 6 values, but following do not work:
print allv/1 ; => gives a (desired is 1)
print allv/2 ; => gives b (desired is 2)
print allv/3 ; => gives none (desired is 3)
I tried following function to combine values in one series:
mycombine: function [ll][
temp: []
foreach l ll [
repeat i length? l [
temp: append temp l/:i ] ]
temp]
mycombine [a b]
But above gives error:
*** Script Error: length? does not allow word! for its series argument
*** Where: length?
*** Stack: rncombine
The series has got converted into word and is not working.
How can I solve this?
Just append
a: [1 2 3]
b: [4 5 6 7]
c: [8 9 10]
d: [11 12 13 14]
>> allv: append a b
== [1 2 3 4 5 6 7]
>> a
== [1 2 3 4 5 6 7]
does what you want. But beware even a contains all values, as you have appendend the values of b to the block a. If you want a new block you have to use
allv: append copy a b
If you want to append more series you can do
>> foreach x [a b c d] [ append [] reduce x]
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14]
Instead of reduce also get x is working.
Another way of combining
>> compose [(a) (b) (c)]
== [1 2 3 4 5 6 7 8 9 10 ]
I'm new to haskell and I want to sort list of strings. For example I have a list that is in my variable ff that contain three strings ["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"] and I want to sort them so my result should look like ["1 5 6 8 8", "1 2 3 4", "4 5 7 9 9 9"] Here's my code that perfectly works
import System.IO
import Control.Monad
import Data.List
import Data.Function
import Data.Array
import Data.Char
sortNumeric = sortBy (compare `on` (read :: String -> Int))
wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s = case dropWhile p s of
"" -> []
s' -> w : wordsWhen p s''
where (w, s'') = break p s'
main = do
file <- readFile "test.txt"
let ff = map ((!!) (lines file)) [1,3..(length (lines file) - 1)]
let splitString = wordsWhen (==' ') (ff!!0)
let sortedResult = sortNumeric (splitString)
print sortedResult
Problem is with this line let splitString = wordsWhen (==' ') (ff!!0) I always get first element of the list, so only first element is sorted. How can I pass all values of a list? Here's what I tryied to do let splitString = wordsWhen (==' ') (ff!![0..(length(ff)-1)]) unfortunately this doesn't work. Any ideas how to solve this problem?
You can do it easily with map and a niftry trick to use words, sort and then unwords (to restore the whitespace).
Prelude> let ff=["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"]
Prelude> import Data.List
Prelude Data.List> map (unwords . sort . words) ff
["1 5 6 8 8","1 2 3 4","4 5 7 9 9 9"]
Edit: Improvement to correctly sort numeric values:
import Data.List
let ff=["11 8 8 5 6", "11 4 2 3", "5 4 9 7 99 9"]
let sortNumeric = (map show) . sort . (map (read :: String -> Int))
map (unwords . sortNumeric . words) ff
result:
["5 6 8 8 11","2 3 4 11","4 5 7 9 9 99"]