How can I find the first zero's index which is followed by 5 zeros in a list? In case no such zero exists return -1.
Netlogo only returns the first element found in a list with position which makes it difficult/cumbersome.
In the question you say you want -1 back if it isn't found, but that doesn't match the behavior of NetLogo's own position primitive, which returns false if the item isn't found. I'd suggest sticking with the usual NetLogo convention for this.
Recursive solution:
to-report position-of-six-zeros [xs]
if length xs < 6
[ report false ]
if sublist xs 0 6 = [0 0 0 0 0 0]
[ report 0 ]
let recurse position-of-six-zeros butfirst xs
if not is-number? recurse
[ report recurse ]
report 1 + recurse
end
Sample runs:
observer> show position-of-six-zeros [0 0 0 0 0]
observer: false
observer> show position-of-six-zeros [0 0 0 0 0 0 ]
observer: 0
observer> show position-of-six-zeros [1 2 3 0 0 0 0 0 0 4 5 6]
observer: 3
observer> show position-of-six-zeros [1 2 3 0 0 0 0 0 4 5 6]
observer: false
I found a possible solution. Maybe there are smarter ways to achieve the same, but at least this approach should work.
You define a list, the length of the sequence you want to look at and the number, which the sequence should have. Then you call the reporter function (check-sequence) with that information.
The reporter function then uses a while loop. It takes the next length-of-sequence elements and filters this sublist by the specified number-of-interest. If the length of this filtered list is the same as the specified length-of-sequence the function will store the actual position on the whole list (i). If not, the first element of the list will be dropped and the loop runs again. If there are not enough elements left in the list, the loop will stop and set the reporter to -1. Otherwise it will report the starting position of the sequence.
to go
let my-list (list 0 1 2 3 0 0 0 8 9 8)
let length-of-sequence 4
let number-of-interest 0
print check-sequence my-list length-of-sequence number-of-interest
end
to-report check-sequence [a-list sequence number]
let i 0
let stopper 0
let reporter 0
while [stopper = 0]
[
let filtered_sublist filter [? = number] (sublist a-list 0 sequence)
if (length filtered_sublist = sequence)
[
set reporter i
set stopper 1
]
set a-list but-first a-list
set i (i + 1)
if (length a-list < sequence)
[
set stopper 2
]
]
ifelse (stopper = 2)
[ report -1 ]
[ report reporter ]
end
Related
I have a vector 'original' with 10 digits. Now I want to create vector 'adapted' based on 'original'. 'adapted' is supposed to take n random values that are larger than 0 from 'original' in the same position and fill up the rest with 0s, e.g.:
original = [2 3 6 2 0 5 7 2 4 8]
adapted = [2 0 0 0 0 5 0 2 0 0]
to go
let n 3
let vector-dimension 10
let original []
repeat vector-dimension
[set original lput random 10 original]
print original
let adapted []
while [sum (map [ [v1] -> ifelse-value (v1 > 0) [1] [0] ] (adapted)) != n]
[set adapted (map [ [v1] -> ifelse-value ( (vector-dimension / n) * (100 / vector-dimension) > random-float 100) [v1] [0] ] (original)) ]
print adapted
end
This Code works but is slow. How can I do it faster?
How about:
to-report report-rand-n [ base n ]
let indices ( range 0 (length base))
let subset n-of n indices
let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
report out
end
This reporter makes a list of indices (0 through the length of the base passed), then randomly selects n number of those indices to pass to ifelse-value to return either the original value in base (if i is one of the selected indices) or 0.
Testing:
to test
let original [2 3 6 2 0 5 7 2 4 8]
print report-rand-n original 3
print report-rand-n original 3
print report-rand-n original 5
print report-rand-n original 5
end
observer> test
[2 0 6 0 0 0 0 0 4 0]
[2 0 0 0 0 0 0 2 0 8]
[2 0 0 0 0 5 0 2 4 8]
[0 0 6 2 0 5 0 0 0 8]
Edit:
to test
let original [2 3 6 2 0 5 7 2 4 8]
print word "testing: " original
print report-rand-n original 3
let few-digits [ 0 0 0 1 0 0 0 ]
print word "testing: " few-digits
print report-rand-n few-digits 3
print ""
end
to-report report-rand-n [ base n ]
; create list of indices
let indices ( range 0 (length base))
; To address point 1) in your comment:
; keep only indices that correspond to a value > 0 in base
let indices-over-zero filter [ i -> item i base > 0 ] indices
; To address point 2 in your comment:
; If the length of indices over zero is less than n, replace n
; with the length of indices over zero
if length indices-over-zero < n [
set n length indices-over-zero
]
let subset n-of n indices-over-zero
let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
report out
end
I try to figure out, how to create an output that has an equal distribution on the random sample. Based on the code snippet below, the function creates three random numbers for three items in a list. This values gets than compared to each other, and the maximal value of them, gets count. However I am trying to figuring out how to control the randomness by a probability for example 50% (50) 25% (25) 25% (25) N=100.
to numberGenerator
let i 0
set counter_red 0
set counter_blue 0
set counter_green 0
while [i < 100] [
let numberS_red1 random-float 1
let numberS_blue1 random-float 1
let numberS_green1 random-float 1
let usedcolors [red blue green]
let OPstrength1 ( list numberS_red1 numberS_blue1 numberS_green1)
let strategies (map list usedcolors OPstrength1)
print strategies
if (numberS_red1 > numberS_blue1) and (numberS_red1 > numberS_green1)
[set counter_red counter_red + 1]
if (numberS_blue1 > numberS_red1) and (numberS_blue1 > numberS_green1)
[set counter_blue counter_blue + 1]
if (numberS_green1 > numberS_red1) and (numberS_green1 > numberS_blue1)
[set counter_green counter_green + 1]
set i i + 1
]
print counter_red
print counter_blue
print counter_green
end
counter_red = 26
counter_blue = 36
counter_green = 38
you can implement a new function using the netlogo random-normal command which assigns a color. Documentation for the function is at link
I'm working with the matrix extension in NetLogo. I want to be able to modify specific elements of the matrix if they equal some number.
For instance if the value is 0.95 I want to run random 2 on it so it comes out as a 1 or a 0. And if it's a 1.75 it comes out as a 1 or a 2 with random (3 - 1) + 1
This would change my matrix m from this:
let m matrix:from-row-list [[1 0.95 0.95] [2 1 1.75] [1 2 1] ]
to this:
[[1 1 0] [.05 1 2] [.05 .25 1] ]
Thanks
I'm not sure if I understand your updated matrix example- for example, why does the 2 in the second row become 0.05 in the output? I'm assuming you have some other rules for dealing with those numbers. Anyway, I think you can use matrix:map to accomplish what you're after- you may just have to set up the rules in your anonymous reporter to reflect what you're after. Here is an example using the rules you supplied for values of 0.95 and 1.75:
extensions [ matrix ]
to matrix-manipulation
let m matrix:from-row-list [[1 0.95 0.95] [2 1 1.75] [1 2 1] ]
let m2 matrix:map [ i -> val-change i ] m
print matrix:pretty-print-text m2
end
to-report val-change [ val ]
if val = 0.95 [
report random 2
]
if val = 1.75 [
report 1 + random 2
]
report val
end
Output becomes:
[[ 1 0 1 ]
[ 2 1 2 ]
[ 1 2 1 ]]
I have a list of lists of equal lengths, e.g.
[[0 1 0] [2 3 0] [4 4 2] [0 1 0]]
How can I get the list [6 9 2] which sums up the entries in the four lists entrywise?
let _lst [[0 1 0] [2 3 0] [4 4 2] [0 1 0]] show reduce [[?1 ?2] -> (map + ?1 ?2)] _lst
As a procedure:
to-report aggregate-lists [list-of-lists]
report reduce [[?1 ?2] -> (map + ?1 ?2)] list-of-lists
end
Someone who is better at lists will come along and do this more cleanly, but this works.
to testme
let inlist [[0 1 0] [2 3 0] [4 4 2] [0 1 0]]
let outlist []
let ii 0
while [ii < length item 1 inlist ]
[ let items map [ x -> item ii x ] inlist
print items
set outlist lput reduce [ [a b] -> a + b] items outlist
set ii ii + 1
]
print outlist
end
What it does it create a list of the first entries (with let items) and then sums them with the reduce, then moves to the second entries etc.
You may also want to look at this question Netlogo: How to compute sum of items of lists within a list?, which works with individual entries.
I was looking for a "one-liner" and finally produced it:
to-report aggregate-lists [list-of-lists]
report map [ i -> sum (map [li -> item i li] list-of-lists) ] range length item 0 list-of-lists
end
You map a reporter which sums item i of all lists to the vector of indices range length item 0 list-of-lists (would be [0 1 2] in the example).
I build a 2-dimensional array (a matrix) consisting of a vector of vectors:
(setq zero-row [0 0 0 0 0])
=> [0 0 0 0 0]
(setq zero-mat (make-vector 4 zero-row))
=> [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
I'll set the element in row 2, column 3 (0-indexed) to 42 by replacing row 2 with a vector containing the changed element:
(aset zero-mat 2 [0 0 0 42 0])
=> [0 0 0 42 0]
zero-mat
=> [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 42 0] [0 0 0 0 0]]
It works.
Next I try to build a function which takes this approach to set the (i,j)-th element in such a 2-dimensional array:
(defun matrix-set (mat i j elt)
"Set the (i, j)-th element of mat to elt. mat is a vector of the row vectors. Indexing is 0-based in each component."
(let ((vect (aref mat i)))
(aset vect j elt)
(aset mat i vect)
mat))
But this doesn't work:
(setq zero-row [0 0 0 0 0])
=> [0 0 0 0 0]
(setq zero-mat (make-vector 4 zero-row))
=> [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
(matrix-set zero-mat 2 3 42)
=> [[0 0 0 42 0] [0 0 0 42 0] [0 0 0 42 0] [0 0 0 42 0]]
It looks like all the rows of the array are linked to the same vector, so changing that vector changes all the rows.
So two questions: (1) Why is this happening in the second case, but not the first? (2) How can I fix this (so I can access the (i, j)-th entry of a 2-dim. array represented this way)?
(I was originally writing a little routine to add two matrices, represented as vectors of vectors as above, and ran into the same problem. I think the stripped-down example above may make the problem clearer.)
In the first case you are replacing an element in the "outer" vector by another vector (while other three "inner" vectors still point all to the same element). In the second case you replace an element in the "inner" vector (and you have only one inner vector duplicated four times, as per your example. A simple way to initialize vector to different distinct vectors would be something like this:
(let ((i 0) (new-vector (make-vector 4 nil))
(while (< (progn (aset new-vector i (make-vector 5 0))
(incf i))
(length new-vector)))
Sorry if there are any typos, was writing it in-place. But the idea should be simple enough to figure it out.