Netlogo select min first value of lists of lists - list

I am looking for a solution in Netlogo to get a value from a list of lists with the minimum pair value.
((value1,value2)(value1,value2)...)
As an example I have a list:
ListofLists = ((2,3)(5,8)(1,9))
I want to select the list with the minimum first value. --> here (1,9) and write the second value out of it.
Goal: Get 9!
my try looks like this:
ListofLists = ((2,3)(5,8)(1,9))
let ChoosedList []
set ChoosedList min (item 0 ListofLists)
set ChoosedValue item 1 ChoosedList
Do you have a solution for this?

The easiest way to do this is to sort the list of lists by the first element of each sublist, then take the second element of the first sublist in the sorted list of lists. Here it is in stages:
let sorted-list sort-by [[a b] -> item 0 a < item 0 b] [[2 3] [5 8] [1 9]]
let ChoosedList first sorted-list
let ChoosedValue item 1 of ChoosedList
or, in one line,
let ChoosedValue item 1 first sort-by [[a b] -> item 0 a < item 0 b] [[2 3] [5 8] [1 9]]
sort-by is very useful for sorting lists of lists.

Related

Filtering a list of lists based on a variable number of combinations in Netlogo

Suppose I have a list of lists I want to filter. The list is such that, in each element, the first two strings are the contents
I want to keep, the third number is the number of times it should appear in the filtered list, and the
last element is the value of the list determining what particular combination appears.
The idea is to keep only the n most valuable items of each, where n is the third element of each list inside, and the value is
determined by the last entry, but also, if there are less combinations than the third item, keep as many as possible.
Thus, in the example below, I would like to have only the first "a", "b" combination, keep the first two "a" "c" ones,
and retain the last, (even though there is no further "a" "d" combinations in it):
I have been trying to use several combinations of filter and thought about ways to retain list elements,
without success for this particular problem.
to setup
let temp-example []
set temp-example [["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 4] ["a" "c" 2 2]
["a" "c" 2 1] ["a" "d" 4 1]]
end
Desired output is the following list:
[["a" "b" 1 5]["a" "c" 2 4]["a" "c" 2 2] ["a" "d" 4 1]]
I'm sure one of the heavyweights around here will chime in soon with a one-or-two line solution, but for now I think this does what you're after. With these reporters:
to-report multifilter [ list_ ]
; Get the content pairs
let content-pairs remove-duplicates map [ i -> sublist i 0 2 ] list_
; Reorganize list into sublists for each content pair
let by-content-pairs map [ i -> filter [ j -> sublist j 0 2 = i ] list_ ] content-pairs
; Sort the sublists
let sorted-by-value map [ i -> sort-with 3 i ] by-content-pairs
; Keep only first n items of each sublist,
report reduce sentence map [ i -> keep-n 2 i ] sorted-by-value
end
to-report sort-with [ ind lst ]
; Sort the sublists by one of their indexed values
report sort-by [ [ a b ] -> ( item ind a ) > ( item ind b ) ] lst
end
to-report keep-n [ ind lst ]
; Keep only as many values as are passed by ind, or the length
; of the list, whichever value is smaller
let n item ind first lst
if n > length lst [
set n length lst
]
report sublist lst 0 n
end
Call multifilter on a list with the format you've shown and you should get your desired output:
to filter-multi
let temp-example [
["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 1]
["a" "c" 2 4] ["a" "c" 2 2] ["a" "d" 4 1]
]
print multifilter temp-example
end
Output:
[[a b 1 5] [a c 2 4] [a c 2 2] [a d 4 1]]
Another example:
to filter-multi
let temp-example [
["a" "b" 1 31] ["a" "b" 1 15] ["a" "b" 1 -53] ["a" "b" 1 10] ["a" "b" 1 3000]
["a" "c" 2 1] ["a" "c" 2 4] ["a" "c" 2 2] ["a" "c" 2 -10] ["a" "c" 2 14] ["a" "c" 2 40]
["a" "d" 4 1] ["a" "d" 4 12]
]
print multifilter temp-example
end
Output:
[[a b 1 3000] [a c 2 40] [a c 2 14] [a d 4 12] [a d 4 1]]
I think this more or less answers it as well:
to-report frequency [an-item a-list]
report length (filter [ i -> i = an-item] a-list)
end
; Reporter to keep the n most valuable combinations
to-report take [n xs]
report sublist xs 0 min list n (length xs)
end
to go
set temp-1[]
set temp-2[]
set temp-3[]
set temp-4[]
foreach temp-example[[i] ->
set temp-1 lput (list item 0 i item 1 i) temp-1
set temp-2 lput item 2 i temp-2]
foreach temp-1[[j] ->
set temp-3 lput frequency j temp-1 temp-3
]
;First: obtain all existing combinations between the two letters:
foreach (range 0 (length temp-example)) [[j]->
ifelse item j temp-2 <= item j temp-3 [set temp-4 lput take (item j temp-2)
filter [i -> (list item 0 i item 1 i) = item j temp-1] temp-example temp-4];
[set temp-4 lput item j temp-example temp-4]; caso contrario, colocar so ate aos
item 2 j:
]
show remove-duplicates temp-4
end

How to replace occurrence of an element with multiple elements in a sequence?

So, I have a list of items. I want to replace each occurrence of an item based on a criteria with a set of elements in it's place.
Ideally, map can let you convert a list of N elements into another list of N elements but here the length will increase as we insert more elements at index where we had other individual elements replaced by a list of elements in place.
As proposed by #Lee you can do it using mapcat.
E.g:
(mapcat #(if (even? %) [% %] [%]) (range 10))
will result into:
=> (0 0 1 2 2 3 4 4 5 6 6 7 8 8 9)
Rather than map, you can use reduce, starting with an empty accumulator collection [].
(reduce #(conj %1 (dec %2) %2)
[]
[1 3 5 7])
So here, starting with a collection of odd numbers [1 3 5 7], we are adding extra even numbers into the sequence. Output is:
[0 1 2 3 4 5 6 7]

netlogo lists: iterating over two lists

I have two lists, both will always be the same length. The first is binary and says whether an agent will move this round, the second contains a set of agents that will need to do something, based on the first list. Something like:
list1 = [0 1 1 1 0]
list2 = [turtle-1 turtle-2 turtle-55 turtle-6 turtle-8]
My objective is to create a third list with only the active turtles in it. Accordingly this list will comprise: turtle-2 turtle-55 and turtle-6. What's the best way to do this?
Like this:
map last filter [first ? = 1] (map list list1 list2)
sample run:
observer> crt 10
observer> set list1 [0 1 1 1 0]
observer> set list2 map turtle [1 2 5 6 8]
observer> show map last filter [first ? = 1] (map list list1 list2)
observer: [(turtle 2) (turtle 5) (turtle 6)]
I am not sure how you can do it with map (Map is cleaner and more efficient) but with foreach you can do it as follow :
to test-lists
let list3 []
foreach list2 [
if (item (position ? list2) list1 = 1)[
set list3 lput ? list3
]
]
print (word "List1 is " list1)
print (word "List2 is " list2)
print (word "List3 is " list3)
end
This is the output:
List1 is [0 1 1 1 0]
List2 is [(turtle 1) (turtle 2) (turtle 55) (turtle 6) (turtle 8)]
List3 is [(turtle 2) (turtle 55) (turtle 6)]

List difference (omit one list from other list) in NetLogo

In case we want to omit one list from other list in Netlogo , how we should write the code?
For example, first list is [1 2 3 4 5]
And second list is [4 5]
In this case what code should be written to remove list 2 from list 1 so as to having a new list comprises of 1, 2 and 3?
Code:
to-report difference [l1 l2]
report filter [not member? ? l2] l1
end
Sample runs:
observer> show difference [1 2 3 4 5] [4 5]
observer: [1 2 3]
observer> show difference [1 2 3 6] [1 2 3 4 5]
observer: [6]

Doseq evaluates 1 x for every y. Is there any way to make it evaluate 1 x for 1 y and so on in Clojure?

I wasn't really sure how to phrase the name of this thread, so if you can clarify it any, please do so.
My example code is this:
(doseq [x [1 2 3] y [3 2 1]] (println (str x y)))
The output of that code is:
13
12
11
23
22
21
33
32
31
nil
I understand that list comprehensions, and doseq both evaluate like this. Is there another way to do this, so that instead of 1 element of x being used for every element of y, and so on, 1 element of x is used with 1 element of y and so on, so that the output would instead be:
13
22
31
Sorry if I'm not phrasing this right, I just can't seem to put it in words right.
EDIT: I think you can do this in Haskell with list comprehensions and a language extension. ParallelListComps or something.
You can simply do
(doseq [[x y] (map vector [1 2 3] [3 2 1])]
(println (str x y)))
(partition 2
(interleave [1 2 3] [3 2 1]))
interleave yields a sequence of alternating elements from the given sequences and partition groups this sequence into sequences of n elements.
This is more succint:
(doall (map println [1 2 3] [3 2 1]))